home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-10 | 132.2 KB | 2,833 lines |
-
-
-
-
-
-
-
-
-
- AVRIL Technical Reference
- Version 2.0
- March 28, 1995
-
- Bernie Roehl
-
-
-
- Note: This is the technical reference manual for version 2.0 of
- AVRIL. The tutorial is a separate document. The appendices for
- this technical reference manual are also stored separately.
-
- This document describes AVRIL from a technical perspective,
- and explains the data types and functions that are available.
- Anything that is not documented here should not be used, since
- it's subject to change in future releases of AVRIL. Also keep in
- mind that some of the routines described below may be implemented
- as macros, and that this may also change in future releases; none
- of your code should assume that any particular routine is either
- a macro or a real function.
-
- There are a number of important concepts that are essential
- to an understanding of how AVRIL works. Let's start by examining
- them.
-
- Basic Data Types
-
- AVRIL uses a left-handed coordinate system; if the X axis
- points to the right, and the Y axis points up, then Z points
- straight ahead. If you're looking at the origin from the
- positive end of an axis, a clockwise rotation is a positive
- rotation angle.
-
- Distances in AVRIL are represented by vrl_Scalars, and
- rotation angles by vrl_Angles. AVRIL can be compiled to use
- either floating point or fixed point, so it's important to use
- the vrl_Scalar and vrl_Angle types for portability. vrl_Scalars
- should always be treated as (long) integer values, regardless of
- whether floating or fixed point is used. vrl_Angles are always
- measured in degrees (converted to the internal vrl_Angle format,
- of course). A third fundamental data type is vrl_Factor, which
- is used for things like the return value of trig functions; a
- special constant called VRL_UNITY is #defined to be a vrl_Factor
- of 1.
-
- In a floating point implementation, all three types
- (vrl_Scalars, vrl_Angles and vrl_Factors) are stored as floats;
- in a fixed-point implementation, they're all 32-bit integers
- (which will be "long" on many systems). The following macros are
-
- AVRIL Technical Reference Manual 1
-
-
-
-
-
- provided for converting between floating point (or regular
- integers) and the three special types:
-
- float2scalar(float);
- scalar2float(vrl_Scalar);
-
- float2angle(float);
- angle2float(vrl_Angle);
-
- float2factor(float);
- factor2float(vrl_Factor);
-
- Several routines are provided to support portable multiplication
- and division of the types:
-
- vrl_Factor vrl_ScalarDivide(vrl_Scalar a, vrl_Scalar b);
- vrl_Scalar vrl_ScalarMultDiv(vrl_Scalar a, vrl_Scalar b, vrl_Scalar c);
- vrl_Scalar vrl_FactorMultiply(vrl_Factor a, vrl_Scalar b);
-
- The first of these routines simply divides two vrl_Scalars and
- returns a vrl_Factor result; the absolute value of a should be
- less than or equal to the absolute value of b. The second
- routine multiplies two vrl_Scalars and divides by a third, using
- a 64-bit intermediate result; in other words, it computes
- (a*b)/c. The third routine multiplies a vrl_Factor by a
- vrl_Scalar and returns a vrl_Scalar result; it can also be used
- for multiplying two vrl_Factors, or an integer or long value by a
- vrl_Factor. The order of the operands is significant, because C
- automatically promotes ints to longs.
-
- In floating-point implementations of AVRIL, there may be
- occasions where the computed value of a vrl_Scalar has a
- fractional part; in such cases you should use the following
- function:
-
- vrl_Scalar vrl_ScalarRound(vrl_Scalar value);
-
- to round to the nearest valid vrl_Scalar value. To take the
- absolute value of a vrl_Scalar, use the function
-
- vrl_Scalar vrl_ScalarAbs(vrl_scale value);
-
- There are currently two trig routines, vrl_Sine() and
- vrl_Cosine(); they both take vrl_Angles as parameters and return
- vrl_Factors:
-
- vrl_Factor vrl_Sine(vrl_Angle angle);
- vrl_Factor vrl_Cosine(vrl_Angle angle) ;
-
- The routine vrl_MathInit() should be called before calling any of
- the trig functions; it pre-computes the trig tables. This is
- done in the vrl_SystemStartup() routine (found in system.c).
-
- AVRIL Technical Reference Manual 2
-
-
-
-
-
- Positions on the screen (i.e., pixel coordinates) are
- represented using the vrl_ScreenPos type, for future portability.
- Fractional screen positions (used in scan-converting polygons)
- are represented using the vrl_ScreenCoord type. This type is
- currently used only by the vrl_Display family of routines.
-
- There are several other basic types used in AVRIL: vrl_Time
- is a measure of elapsed time in ticks, vrl_Color is used to
- represent colors (both 8-bit and 24-bit) and vrl_Boolean is a
- true/false type value (non-zero being true). The types vrl_32bit
- and vrl_unsigned32bit are used for signed and unsigned 32-bit
- numbers, and vrl_16bit and vrl_unsigned16bit are used for signed
- and unsigned 16-bit numbers. The function
-
- vrl_32bit abs32(vrl_32bit value);
-
- will return the absolute value of a 32-bit number, independent of
- whether 32-bit values are of type int or type long.
-
- Vectors
-
- A vrl_Vector is a three-element array, which can be indexed
- by the #defined constants X, Y and Z; for example, if v is a
- vector then v[X] is the X-component of the vector. In general,
- vrl_Vectors are made up of three vrl_Scalars; however, a
- normalized vector (such as a facet normal, a basis vector, or a
- vector that's been normalized using the vrl_VectorNormalize()
- function) will actually have vrl_Factors as elements. The
- following functions perform fundamental operations on
- vrl_Vectors:
-
- void vrl_VectorCreate(vrl_Vector result, vrl_Scalar x, vrl_Scalar y, vrl_Scalar z);
- void vrl_VectorCopy(vrl_Vector destination, vrl_Vector source);
- void vrl_VectorAdd(vrl_Vector result, vrl_Vector v1, vrl_Vector v2);
- void vrl_VectorSub(vrl_Vector result, vrl_Vector v1, vrl_Vector v2);
- void vrl_VectorNegate(vrl_Vector v);
- vrl_Factor vrl_VectorDotproduct(vrl_Vector v1, vrl_Vector v2);
- vrl_Scalar vrl_VectorCrossproduct(vrl_Vector result, vrl_Vector v1, vrl_Vector v2);
- vrl_Scalar vrl_VectorMagnitude(vrl_Vector v);
- void vrl_VectorNormalize(vrl_Vector v);
- vrl_Scalar vrl_VectorDistance(vrl_Vector v1, vrl_Vector v2);
- void vrl_VectorScale(vrl_Vector v, vrl_Scalar newmag);
- void vrl_VectorRescale(vrl_Vector v, vrl_Scalar newmag);
- void vrl_VectorPrint(FILE *out, char *str, vrl_Vector v);
- vrl_Boolean vrl_VectorEqual(vrl_Vector v1, vrl_Vector v2);
- void vrl_VectorZero(vrl_Vector v);
-
- The vrl_VectorCreate() function takes three vrl_Scalars and
- assembles them into a vrl_Vector. The vrl_VectorCopy(),
- vrl_VectorAdd() and vrl_VectorSub() routines do element-by-
- element copies, additions and subtractions of vrl_Vectors. The
- vrl_VectorNegate() function reverses the direction of a
-
- AVRIL Technical Reference Manual 3
-
-
-
-
-
- vrl_Vector by flipping the sign of each of its components. The
- vrl_VectorDotproduct() routine computes the dot product (inner
- product) of two vectors; at least one of the vectors should be
- normalized for this to work properly.
-
- The vrl_VectorCrossproduct() routine computes the vector
- cross product (outer product) of two vectors. This is likely to
- be slow, since it normalizes the result (which involves doing a
- square root operation). It returns the magnitude of the vector
- prior to normalization. The vrl_Magnitude() routine returns the
- magnitude of a vector, and the vrl_VectorNormalize() routine
- scales a vector so that it has a magnitude of 1.
-
- The vrl_VectorDistance() routine takes two vrl_Vectors (each
- representing a point in space) and computes the distance between
- those two points. The vrl_Scale() function takes a normalized
- vrl_Vector and scales all its components by the given amount; the
- vrl_Rescale() function takes a non-normalized vector and re-
- scales it to have the specified magnitude.
-
- The vrl_VectorPrint() routine prints out a message followed
- by the values of each of the components of the vrl_Vector,
- enclosed in square brackets. Do not attempt to write to the
- screen with this routine, since it will not work well in graphics
- mode.
-
- The vrl_VectorEqual() routine returns a non-zero value if
- the two vrl_Vectors are identical, and vrl_VectorZero() sets the
- components of a vrl_Vector to zero. The [0,0,0] vector is
- sometimes needed, so a global vrl_Vector variable called
- vrl_VectorNULL is defined.
-
- Matrices
-
- A vrl_Matrix is a 4 by 3 array that stores location and
- orientation information. All AVRIL matrices are homogeneous; the
- upper 3 by 3 submatrix stores rotation information and the last
- 3-element row stores a translation vector. You should never have
- to deal with the vrl_Matrix type directly. However, in case you
- do have a need to deal with actual matrices, the following
- routines are provided:
-
- void vrl_MatrixIdentity(vrl_Matrix m);
- void vrl_MatrixCopy(vrl_Matrix result, vrl_Matrix m);
- void vrl_MatrixMultiply(vrl_Matrix result, vrl_Matrix m1, vrl_Matrix m2);
- void vrl_MatrixInverse(vrl_Matrix result, vrl_Matrix m);
- void vrl_MatrixRotX(vrl_Matrix m, vrl_Angle angle, vrl_Boolean leftside);
- void vrl_MatrixRotY(vrl_Matrix m, vrl_Angle angle, vrl_Boolean leftside);
- void vrl_MatrixRotZ(vrl_Matrix m, vrl_Angle angle, vrl_Boolean leftside);
- void vrl_MatrixRotVector(vrl_Matrix m, vrl_Angle angle, vrl_Vector vector,
- vrl_Boolean leftside);
- void vrl_MatrixResetRotations(vrl_Matrix m);
-
- AVRIL Technical Reference Manual 4
-
-
-
-
-
- void vrl_MatrixGetBasis(vrl_Vector v, vrl_Matrix m, int axis);
- void vrl_MatrixSetBasis(vrl_Matrix m, vrl_Vector v, int axis);
- void vrl_MatrixTranslate(vrl_Matrix result, vrl_Scalar x, vrl_Scalar y, vrl_Scalar z);
- void vrl_MatrixSetTranslation(vrl_Matrix result,
- vrl_Scalar x, vrl_Scalar y, vrl_Scalar z);
- void vrl_MatrixGetTranslation(vrl_Vector v, vrl_Matrix m);
- void vrl_MatrixGetRotations(vrl_Matrix m, vrl_Angle *rx, vrl_Angle *ry, vrl_Angle *rz);
-
- The vrl_MatrixIdentity() function sets the matrix to zeroes,
- except for the diagonal elements which are set to VRL_UNITY. The
- vrl_MatrixCopy() and vrl_MatrixMultiply() routines are used to
- copy and multiply matrices, and the vrl_MatrixInverse() routine
- computes the matrix inverse. The various rotation functions
- apply a rotation around X, Y, Z or a specified vector by a given
- angle; the vrl_MatrixResetRotations() routine sets all the
- rotations to zero. Several of the vrl_Matrix routines use a
- leftside parameter; a non-zero value for this parameter specifies
- that the transformation should be applied as a pre-multiplication
- instead of a post-multiplication.
-
- The function vrl_MatrixGetBasis() gets one of the basis
- vectors of the rotation part of the matrix; this is equivalent to
- (but faster than) transforming an axis-aligned unit vector by the
- matrix. In other words, vrl_MatrixGetBasis(v, m, X) is
- equivalent to transforming the vector [1,0,0] by the rotation
- part of the matrix m and storing the result in the vector v.
-
- The vrl_MatrixTranslate() routine applies a translation to
- the matrix, and vrl_MatrixSetTranslation() sets the actual
- translation part of the matrix. The vrl_MatrixGetTranslation()
- routine fills the given vector with the current translation part
- of the matrix, and vrl_MatrixGetRotations() gets the angles
- which, when applied in the order Y, X, Z, produces the rotation
- part of the matrix.
-
- Transforms
-
- You should never have to use any of the transform functions
- directly; this is all handled for you by AVRIL. A vector can be
- transformed by a matrix, or each component of the transform (X, Y
- or Z) can be computed separately:
-
- void vrl_Transform(vrl_Vector result, vrl_Matrix m, vrl_Vector v);
- vrl_Scalar vrl_TransformX(vrl_Matrix m, vrl_Vector v);
- vrl_Scalar vrl_TransformY(vrl_Matrix m, vrl_Vector v);
- vrl_Scalar vrl_TransformZ(vrl_Matrix m, vrl_Vector v);
-
- Coordinate Systems
-
- AVRIL allows objects to be translated or rotated in five
- different coordinate systems. This may seem like a lot, but
- they're easy to get used to. An object can be moved in its own
-
- AVRIL Technical Reference Manual 5
-
-
-
-
-
- local coordinate system, the coordinate system of the object it's
- attached to, the "world" coordinate system, the viewer's
- coordinate system, or the coordinate system of another object.
-
- For example, consider a bicycle on an open train car. The
- bicycle is facing sideways, so that if you were sitting on it
- you'd be watching the scenery go by on the right side of the
- train. The train itself is moving northeast. If we translate
- the bicycle along the positive Z axis in its local coordinate
- system, it will travel sideways off the train car, in a south-
- easterly direction. If we move it in the positive Z direction of
- its parent, it will move to the rider's left, towards the front
- of the train (northeast). If we move it in the positive Z
- direction in the world, it will move due north. If we're looking
- at it from directly above, moving the bicycle in the viewer's
- positive Z direction would send it through the train car and down
- into the ground. If a bird is flying due south, then moving the
- bicycle in the positive Z direction relative to the bird would
- make the bike move due south.
-
- We represent these various coordinate systems by the
- constants VRL_COORD_LOCAL, VRL_COORD_PARENT, VRL_COORD_WORLD, and
- VRL_COORD_OBJREL. The view-relative coordinate system is just a
- special case of the VRL_COORD_OBJREL coordinate frame, with the
- viewer as the object that the movement should be relative to.
-
- Worlds
-
- In AVRIL, a virtual world is a collection of objects, light
- sources, virtual cameras and miscellaneous attributes. You can
- have any number of worlds within a single AVRIL application;
- they're distinct from each other, and you can switch between them
- whenever you like.
-
- When you run an AVRIL program, a default world is created
- and initialized for you; if you only plan on having one world in
- your application, you don't have to do anything special. If you
- want to create additional worlds, you can simply declare
- variables of type vrl_World and initialize them by calling
- vrl_WorldInit(&yourworld); however, it's probably better to
- dynamically allocate them using vrl_malloc(). In fact, the
- simplest way to create a world is with the vrl_WorldCreate()
- function, which allocates the space and initializes the world for
- you. To make a given world current, use the
- vrl_WorldSetCurrent() function; the vrl_WorldGetCurrent()
- function can be used to get a pointer to the current world.
-
- vrl_World *vrl_WorldInit(vrl_World *world);
- vrl_World *vrl_WorldCreate(void);
- void vrl_WorldSetCurrent(vrl_World *world);
- vrl_World *vrl_WorldGetCurrent(void);
-
-
- AVRIL Technical Reference Manual 6
-
-
-
-
-
- You can easily add objects, light sources and cameras to the
- current world, and remove them; you can also count how many of
- each the current world contains, and get pointers to the linked
- list of lights, linked list of cameras and the hierarchical tree
- of objects You can also find lights, cameras and objects by
- name.
-
- void vrl_WorldAddLight(vrl_Light *light);
- void vrl_WorldRemoveLight(vrl_Light *light);
- vrl_Light *vrl_WorldFindLight(char *name);
-
- void vrl_WorldAddCamera(vrl_Camera *camera);
- void vrl_WorldRemoveCamera(vrl_Camera *camera);
- vrl_Camera *vrl_WorldFindCamera(char *name);
-
- void vrl_WorldAddObject(vrl_Object *obj);
- void vrl_WorldRemoveObject(vrl_Object *obj);
- vrl_Object *vrl_WorldFindObject(char *name);
-
- int vrl_WorldCountObjects(void);
- int vrl_WorldCountLights(void);
- int vrl_WorldCountCameras(void);
-
- vrl_Light *vrl_WorldGetLights(void);
- vrl_Light *vrl_WorldGetCameras(void);
- vrl_Object *vrl_WorldGetObjectTree(void);
-
- If you need to iterate through the linked list of lights or
- cameras, you can use the functions
-
- vrl_Light *vrl_LightGetNext(vrl_Light *light);
- vrl_Camera *vrl_CameraGetNext(vrl_Camera *camera);
-
- You can also obtain information about the total number of facets
- in the world, the minimum and maximum bounds of the world, the
- center of the world and the radius of the world's bounding sphere
- using these functions:
-
- int vrl_WorldCountFacets(void);
- void vrl_WorldGetBounds(vrl_Vector v1, vrl_Vector v2);
- void vrl_WorldGetCenter(vrl_Vector v);
- vrl_Scalar vrl_WorldGetSize(void);
-
- Each world has a "current camera" through which the world is
- seen; you can set the current camera, or get a pointer to it
- using these routines:
-
- void vrl_WorldSetCamera(vrl_Camera *cam);
- vrl_Camera *vrl_WorldGetCamera(void);
-
-
-
-
- AVRIL Technical Reference Manual 7
-
-
-
-
-
- The clearing of the screen prior to each frame, and the use (and
- colors) of the horizon, are controlled by the following
- functions:
-
- void vrl_WorldSetScreenClear(int n);
- int vrl_WorldGetScreenClear(void);
- void vrl_WorldToggleScreenClear(void);
-
- void vrl_WorldSetHorizon(int n);
- int vrl_WorldGetHorizon(void);
- void vrl_WorldToggleHorizon(void);
-
- void vrl_WorldSetGroundColor(int color);
- int vrl_WorldGetGroundColor(void);
-
- void vrl_WorldSetSkyColor(int color);
- int vrl_WorldGetSkyColor(void);
-
- The rate at which the user moves and turns is controlled by the
- "turn" step and the "move" step. In addition, the movement
- "mode" can be set to 0 or 1; if it's 1 (the default) then simple
- movement can move the user vertically, otherwise they stay on the
- ground. Note that these are really only suggestions, and it's up
- to the application to make use of them.
-
- void vrl_WorldSetMovementMode(int n);
- int vrl_WorldGetMovementMode(void);
- void vrl_WorldToggleMovementMode(void);
-
- void vrl_WorldSetMovestep(vrl_Scalar distance);
- vrl_Scalar vrl_WorldGetMovestep(void);
-
- void vrl_WorldSetTurnstep(vrl_Angle angle);
- vrl_Angle vrl_WorldGetTurnstep(void);
-
- There's a flag, stored in the world data structure, which
- indicates whether or not the world is being rendered
- stereoscopically; the following routines access that flag:
-
- void vrl_WorldSetStereo(int n);
- int vrl_WorldGetStereo(void);
- void vrl_WorldToggleStereo(void);
-
- The world data structure also stores a pointer to the stereo
- configuration being used. That pointer can be accessed using the
- following routines:
-
- vrl_WorldSetStereoConfiguration(conf);
- vrl_StereoConfiguration *vrl_WorldGetStereoConfiguration(void);
-
-
-
-
- AVRIL Technical Reference Manual 8
-
-
-
-
-
- In addition to the standard, "cyclopean" camera, there are
- cameras in the world for the left and right eyes. The functions
- to access them are:
-
- void vrl_WorldSetLeftCamera(cam);
- vrl_Camera *vrl_WorldGetLeftCamera(void);
- void vrl_WorldSetRightCamera(cam);
- vrl_Camera *vrl_WorldGetRightCamera(void);
-
- Finally, additional aspects of the virtual world such as the
- ambient light level and the "scale factor" (the number of real-
- world millimeters per unit of distance in the virtual world) can
- be set and queried using the following functions:
-
- void vrl_WorldSetAmbient(vrl_Factor ambient);
- vrl_Factor vrl_WorldGetAmbient(void);
-
- void vrl_WorldSetScale(vrl_Scalar scale);
- vrl_Scalar vrl_WorldGetScale(void);
-
- Objects
-
- Objects are the most important entities in a virtual world.
- All objects have a location and orientation, and they can be
- attached to each other in a tree-structured hierarchy. Each
- object can have a shape (i.e. geometric description) and a
- surface map. You can create an object statically (by declaring a
- variable of type vrl_Object) or dynamically (either by using
- vrl_malloc() to allocate the space and vrl_ObjectInit() to
- initialize it, or by simply calling vrl_ObjectCreate()). If you
- use vrl_ObjectCreate(), you can optionally specify a shape for
- the object to use; if you don't want to assign a shape, use NULL.
- You can also destroy objects using vrl_ObjectDestroy().
-
- vrl_Object *vrl_ObjectInit(vrl_Object *obj);
- vrl_Object *vrl_ObjectCreate(vrl_Shape *shape);
- void vrl_ObjectDestroy(vrl_Object *object);
-
- You can create an exact copy of an object using the function
-
- vrl_Object *vrl_ObjectCopy(vrl_Object *obj);
-
- Note that the newly-created object will share all the same
- properties (including the shape and surface map) as the original
- and will be in the exact same location as the original; you
- should probably move it. The copy will have nothing attached to
- it (it doesn't inherit children from the original), and will be a
- sibling of the original (sharing the same parent, if any).
-
- Objects can be rotated around any of the axes, in any coordinate
- frame, using the following function:
-
-
- AVRIL Technical Reference Manual 9
-
-
-
-
-
- void vrl_ObjectRotate(vrl_Object *obj, vrl_Angle angle, int axis,
- vrl_CoordFrame frame, vrl_Object *relative_to);
-
- The axis is one of the defined constants X, Y or Z. The frame is
- one of the coordinate frames discussed earlier. If the frame is
- VRL_COORD_OBJREL, then the relative_to parameter points to the
- object that motion should be relative to. For example, to rotate
- an object 45 degrees around the viewer's Z axis, you would make
- the following call:
-
- vrl_ObjectRotate(obj, float2angle(45), Z,
- VRL_COORD_OBJREL, vrl_CameraGetObject(vrl_WorldGetCamera()));
-
- You can also orient an object to "look" in a particular direction
- using the function
-
- void vrl_ObjectLookAt(vrl_Object *obj, vrl_Vector forward, vrl_Vector up);
-
- The object will be rotated so that it's Z axis points along the
- forward vector, and its Y axis points in the general direction of
- the up vector. Note that the actual Y orientation may be
- different, unless you make sure that up is perpendicular to
- forward. The up and forward vectors are specified in world
- coordinates, and should both be unit vectors; you may find the
- vrl_VectorNormalize() function handy for this.
-
- Translations of an object are done with the following function:
-
- void vrl_ObjectTranslate(vrl_Object *obj, vrl_Vector v,
- vrl_CoordFrame frame, vrl_Object *relative_to);
-
- The object is moved along the vrl_Vector v in the specified
- frame. The meaning of the relative_to parameter is the same as
- it was for vrl_ObjectRotate().
-
- The vrl_ObjectRotate() and vrl_ObjectTranslate() routines both
- apply a rotation to the current state of the object. If you wish
- to make the rotations absolute, call vrl_ObjectRotReset(obj). If
- you wish to make translations absolute, call
- vrl_ObjectVectorMove(obj, vrl_VectorNULL) to set the
- translations to zero. These should both be done before applying
- the vrl_ObjectRotate() and vrl_ObjectTranslate() functions.
-
- The vrl_ObjectRotate() and vrl_ObjectTranslate() functions should
- be used for all object rotation and translation. Some older
- functions are also provided for rotating and moving objects
- relative to their parent (one of the more common cases); they are
- as follows:
-
- void vrl_ObjectMove(vrl_Object *obj, vrl_Scalar x, vrl_Scalar y, vrl_Scalar z);
- void vrl_ObjectRelMove(vrl_Object *obj, vrl_Scalar x, vrl_Scalar y, vrl_Scalar z);
- void vrl_ObjectRotX(vrl_Object *obj, vrl_Angle angle);
-
- AVRIL Technical Reference Manual 10
-
-
-
-
-
- void vrl_ObjectRotY(vrl_Object *obj, vrl_Angle angle);
- void vrl_ObjectRotZ(vrl_Object *obj, vrl_Angle angle);
- void vrl_ObjectRotVector(vrl_Object *obj, vrl_Angle angle, vrl_Vector vector);
- void vrl_ObjectRotReset(vrl_Object *obj);
- void vrl_ObjectVectorMove(vrl_Object *obj, vrl_Vector v);
- void vrl_ObjectVectorRelMove(vrl_Object *obj, vrl_Vector v);
-
- An object's current location can be obtained in two ways, either
- component-by-component for each of X, Y and Z, or copied into a
- vector:
-
- vrl_Scalar vrl_ObjectGetWorldX(vrl_Object *object);
- vrl_Scalar vrl_ObjectGetWorldY(vrl_Object *object);
- vrl_Scalar vrl_ObjectGetWorldZ(vrl_Object *object);
- void vrl_ObjectGetWorldLocation(vrl_Object *object, vrl_Vector v);
-
- vrl_Scalar vrl_ObjectGetRelativeX(vrl_Object *object);
- vrl_Scalar vrl_ObjectGetRelativeY(vrl_Object *object);
- vrl_Scalar vrl_ObjectGetRelativeZ(vrl_Object *object);
- void vrl_ObjectGetRelativeLocation(vrl_Object *object, vrl_Vector v);
-
- The World versions of the functions return the absolute world
- coordinates; the Relative versions return the coordinates
- relative to the object's parent.
-
- The rotation angles of objects, either relative to the world or
- to their parent, can be obtained using the following routines:
-
- void vrl_ObjectGetWorldRotations(vrl_Object *object,
- vrl_Angle *rx, vrl_Angle *ry, vrl_Angle *rz);
- void vrl_ObjectGetRelativeRotations(vrl_Object *object,
- vrl_Angle *rx, vrl_Angle *ry, vrl_Angle *rz);
-
- The current world-space orientation of an object's "forward",
- "up" and "right" vectors can be obtained using the following
- routines:
-
- void vrl_ObjectGetForwardVector(vrl_Object *object, vrl_Vector v);
- void vrl_ObjectGetRightVector(vrl_Object *object, vrl_Vector v);
- void vrl_ObjectGetUpVector(vrl_Object *object, vrl_Vector v);
-
- The vectors filled in by these routines will all be normalized.
-
- An object can be attached to another object, or detached from
- whatever object it is currently attached to; you can also find
- out the "parent" of the object:
-
- vrl_Object *vrl_ObjectAttach(vrl_Object *obj, vrl_Object *newparent);
- vrl_Object *vrl_ObjectDetach(vrl_Object *obj);
- vrl_Object *vrl_ObjectGetParent(vrl_Object *obj);
-
-
-
- AVRIL Technical Reference Manual 11
-
-
-
-
-
- The vrl_ObjectAttach() and vrl_ObjectDetach() functions return a
- pointer to the object's previous parent if any. Note that
- movement and rotation in the VRL_COORD_PARENT system (including
- that performed using vrl_ObjectRotX() and other similar
- functions) is carried out relative to the object's parent. In
- other words, if the object is attached to another object, its
- location and orientation will depend on that of its parent; if
- the parent moves, the child will move with it. However, if the
- child moves the parent will stay where it is.
-
- You can find the "root" of an object tree using the following
- function:
-
- vrl_Object *vrl_ObjectFindRoot(vrl_Object *obj);
-
- You can walk an entire object tree, executing a function on each
- node of the tree, using the following routine:
-
- void vrl_ObjectTraverse(vrl_Object *object, int (*function)(vrl_Object *obj));
-
- The function is called once for each object in the hierarchy, and
- is given a pointer to the object it's being called on; if the
- function returns a non-zero value at any point, the tree is not
- processed any further. All parent objects are processed before
- their descendants.
-
- The distance between two objects can be found using
-
- vrl_Scalar vrl_ObjectComputeDistance(vrl_Object *obj1, vrl_Object *obj2);
-
- The shape and surface map of an object can be altered at any
- time, and as often as needed, using the following routines:
-
- void vrl_ObjectSetShape(vrl_Object *object, vrl_Shape *shape);
- vrl_Shape *vrl_ObjectGetShape(vrl_Object *object);
-
- void vrl_ObjectSetSurfacemap(vrl_Object *object, vrl_Surfacemap *map);
- vrl_Surfacemap *vrl_ObjectGetSurfacemap(vrl_Object *object);
-
- Objects can be flagged as invisible (in which case they're not
- drawn) or highlighted (in which case they're drawn with a bright
- outline). They can also have a "layer" property, and individual
- layers can be made visible or invisible, as described later in
- the section on Layers. Note that layer zero is always visible;
- in effect, an object whose layer is zero will appear on all
- layers. The following routines are used to set, query and toggle
- those values:
-
- void vrl_ObjectSetVisibility(vrl_Object *object, int vis);
- int vrl_ObjectGetVisibility(vrl_Object *object);
- void vrl_ObjectToggleVisibility(vrl_Object *object);
-
-
- AVRIL Technical Reference Manual 12
-
-
-
-
-
- void vrl_ObjectSetHighlight(vrl_Object *object, highlight);
- int vrl_ObjectGetHighlight(vrl_Object *object);
- void vrl_ObjectToggleHighlight(vrl_Object *object);
-
- void vrl_ObjectSetLayer(vrl_Object *object, int layer);
- int vrl_ObjectGetLayer(vrl_Object *object);
-
- AVRIL supports the idea of "fixed" objects; you can mark an
- object as fixed or movable, and find out its current status,
- using the following functions:
-
- void vrl_ObjectMakeFixed(vrl_Object *object);
- void vrl_ObjectMakeMovable(vrl_Object *object);
- vrl_Boolean vrl_ObjectIsFixed(vrl_Object *object);
-
- You can also find out the boundaries of an object (in world
- coordinates) using the functions
-
- void vrl_ObjectGetMinbounds(vrl_Object *object, vrl_Vector v);
- void vrl_ObjectGetMaxbounds(vrl_Object *object, vrl_Vector v);
-
- The vectors returned by these two functions can be thought of as
- the opposite corners of the object's bounding box.
-
- AVRIL will normally select a level of detail for an object
- automatically; however, you can override this mechanism on an
- object-by-object basis using two routines to set and get the
- current "forced" rep for an object:
-
- void vrl_ObjectSetRep(vrl_Object *object, vrl_Rep *rep);
- vrl_Rep *vrl_ObjectGetRep(vrl_Object *object);
-
- If you want automatic representation selection to be re-enabled
- for the object, just use vrl_ObjectSetRep(obj, NULL). See the
- section on Representations for details.
-
- Whenever an object moves, all the objects "descended" from that
- object must be updated. The following function will update the
- object and all its descendants:
-
- vrl_Object *vrl_ObjectUpdate(vrl_Object *object);
-
- You should generally only call this once per frame, on the object
- tree for the current world; the macro vrl_WorldUpdate() can be
- used to do this more concisely.
-
- A vrl_Object can have several other properties associated
- with it. These include a name, a function, and some application-
- specific data. The function associated with an object gets
- called whenever the object is processed during the tree-walking
- that vrl_ObjectUpdate() performs. The following routines allow
- you to get and set these additional properties:
-
- AVRIL Technical Reference Manual 13
-
-
-
-
-
- void vrl_ObjectSetName(vrl_Object *obj, char *str);
- char *vrl_ObjectGetName(vrl_Object *obj);
- void vrl_ObjectSetFunction(vrl_Object *obj, vrl_ObjectFunction fn);
- vrl_ObjectFunction *vrl_ObjectGetFunction(vrl_Object *obj);
- void vrl_ObjectSetApplicationData(vrl_Object *obj, void *data);
- void *vrl_ObjectGetApplicationData(vrl_Object *obj);
-
- Shapes
-
- As described earlier, AVRIL keeps shape information separate
- from object descriptions, so that shapes can be re-used by
- multiple objects. Shapes (entities of type vrl_Shape) are
- generally read from PLG files using the vrl_ReadPLG() function,
- described later. You can also create them using the
- vrl_Primitive family of functions, also described later in this
- document. The syntax for PLG files is described in Appendix C.
-
- You can modify a shape after it's been loaded; bear in mind
- that any changes you make to a shape will affect all objects
- using that shape! To re-scale a shape, or shift all the vertices
- in the shape relative to the shape's origin point, use the
- following functions:
-
- void vrl_ShapeRescale(vrl_Shape *shape, float sx, float sy, float sz);
- void vrl_ShapeOffset(vrl_Shape *shape, vrl_Scalar tx, vrl_Scalar ty, vrl_Scalar tz);
-
- After making changes to a shape (or any representation within a
- shape), you should call vrl_ShapeUpdate() to recompute the
- shape's bounds.
-
- void vrl_ShapeUpdate(vrl_Shape *shape);
-
- The vrl_ShapeRescale() and vrl_ShapeOffset() routines call
- vrl_ShapeUpdate() automatically, so you don't have to do it
- again; it's only when you move individual vertices that you need
- to worry about it.
-
- Shapes can have a default surface map, which is used for objects
- that don't set one of their own. A pointer to a shape's default
- surface map can be obtained, or a pointer to a new surfacemap for
- a shape set, by calling the functions
-
- vrl_Surfacemap *vrl_ShapeGetSurfacemap(vrl_Shape *shape);
- void vrl_ShapeSetSurfacemap(vrl_Shape *shape, vrl_Surfacemap *map);
-
- To get a pointer to the representation of a shape that will be
- used at a given on-screen size, use following function:
-
- vrl_Rep *vrl_ShapeGetRep(vrl_Shape *shape, vrl_Scalar size);
-
- To add an additional representation to an existing shape, use the
- function
-
- AVRIL Technical Reference Manual 14
-
-
-
-
-
- void vrl_ShapeAddRep(vrl_Shape *shape, vrl_Rep *rep, vrl_Scalar size);
-
- The size parameter gives the apparent on-screen size in pixels at
- which the shape should be used. You can find out how many
- representations a shape has using the function
-
- int vrl_ShapeCountReps(vrl_Shape *shape);
-
- A shape's name can be set or obtained using the functions
-
- void vrl_ShapeSetName(vrl_Shape *shape, char *str);
- char *vrl_ShapeGetName(vrl_Shape *shape);
-
- Shapes are kept internally in a singly-linked list; if you need
- to iterate through the list, the following two functions can be
- used
-
- vrl_Shape *vrl_ShapeGetList(void);
- vrl_Shape *vrl_ShapeGetNext(vrl_Shape *shape)
-
- You can also locate a shape by name using
-
- vrl_Shape *vrl_ShapeFind(char *name);
-
- Representations
-
- A shape can have any number of representations, at various
- levels of detail. Each representation (vrl_Rep) has a set of
- vertices (each of type vrl_Vector) and a set of facets (each of
- type vrl_Facet). A representation can also have a "sorting type"
- field; this will be explained in more detail in future releases
- of this documentation.
-
- You can traverse the list of representations for a shape,
- calling a function on each representation, by using the following
- routine:
-
- void vrl_ShapeTraverseReps(vrl_Shape *shape, int (*function(vrl_Rep *rep)));
-
- The function is called once for every representation, and is
- given the representation as a parameter. If the function returns
- a non-zero value, the processing of the representation list stops
- at that rep.
-
- The other approach is to iterate through the linked list of
- representations using the functions
-
- vrl_Rep *vrl_ShapeGetFirstRep(vrl_Shape *shape);
- vrl_Rep *vrl_RepGetNext(vrl_Rep *rep);
-
- You can set and get a vrl_Rep's sorting type, find out the
- approximate size (in pixels) at which a rep becomes effective, as
-
- AVRIL Technical Reference Manual 15
-
-
-
-
-
- well as count the number of vertices and facets in a rep using
- the following functions:
-
- void vrl_RepSetSorting(vrl_Rep *rep, int type);
- int vrl_RepGetSorting(vrl_Rep *rep);
-
- int vrl_RepGetSize(vrl_Rep *rep);
-
- int vrl_RepCountVertices(vrl_Rep *rep);
- int vrl_RepCountFacets(vrl_Rep *rep);
-
- There are also "traversal" functions for vertices and facets:
-
- void vrl_RepTraverseVertices(vrl_Rep *rep, int (*function)(vrl_Vector *vertex));
- void vrl_RepTraverseFacets(vrl_Rep *rep, int (*function)(vrl_Facet *facet));
-
- If you need to get or set the values of a vertex's coordinates,
- you can use the functions
-
- void vrl_RepGetVertex(vrl_Rep *rep, int n, vrl_Vector v);
- void vrl_RepSetVertex(vrl_Rep *rep, int n, vrl_Vector v);
-
- Be careful when using vrl_RepSetVertex(); it's easy to move a
- vertex and create non-planar or non-convex facets, which confuse
- the renderer. You can only move vertices safely if you know the
- vrl_Rep is composed entirely of triangles, since by their nature
- triangles are always planar and convex. In any case, be sure to
- call vrl_ShapeUpdate() after moving any vertices.
-
- To support Gouraud shading, functions are provided to compute
- vertex normals by averaging the normal vectors of all the polys
- which share the vertex in a vrl_Rep or a vrl_Shape:
-
- void vrl_RepComputeVertexNormals(vrl_Rep *rep);
- void vrl_ShapeComputeVertexNormals(vrl_Shape *shape);
-
- Make sure that the polygons normals have already been computed
- (by the vrl_ShapeUpdate() function) before calling
- vrl_RepComputeVertexNormals().
-
- There's also a function for computing edge information for a
- representation; currently, this information is not used:
-
- void vrl_RepBuildEdges(vrl_Rep *rep);
-
- Facets
-
- AVRIL's terminology is slightly different from some other VR
- systems; a "facet" is a flat three-dimensional entity, whereas a
- "polygon" is a two dimensional area on the screen. The job of
- the graphics pipeline is to turn facets into polygons.
-
-
- AVRIL Technical Reference Manual 16
-
-
-
-
-
- Facets in AVRIL have an array of integers that specify which
- vertices in the representation should be connected (and in what
- sequence) to form the outline of the facet. Facets also have an
- index into the surface map for an object, to determine what the
- surface properties of the facet should be. They also have a flag
- that indicates whether or not the facet should be highlighted.
-
- The surface index of any facet can be set or queried at any
- time using the following two routines:
-
- void vrl_FacetSetSurfnum(vrl_Facet *facet, int n);
- int void vrl_FacetGetSurfnum(vrl_Facet *facet);
-
- The highlighting of the facet can be set, queried or toggled
- using the following routines:
-
- void vrl_FacetSetHighlight(vrl_Facet *facet, int high);
- int vrl_FacetGetHighlight(vrl_Facet *facet);
- void vrl_FacetToggleHighlight(vrl_Facet *facet);
-
- The number of points in the facet, the index of any particular
- point, or a pointer to the vertex for a particular point, can all
- be obtained using these routines:
-
- int vrl_FacetCountPoints(vrl_Facet *facet);
- int vrl_FacetGetPoint(vrl_Facet *facet, int n);
- vrl_Vector *vrl_FacetGetVertex(vrl_Rep *rep, vrl_Facet *facet, int n);
-
- vrl_Facets can be identified by an ID number. The ID number for
- a vrl_Facet can be set and read, and a vrl_Facet with a
- particular ID can be found, using the following functions:
-
- void vrl_FacetSetId(vrl_Facet *facet, vrl_unsigned16bit n);
- vrl_unsigned16bit vrl_FacetGetId(vrl_Facet *facet);
- vrl_Facet *vrl_RepFindFacet(vrl_Rep *rep, vrl_unsigned16bit id);
-
- Surfaces
-
- AVRIL surfaces are designed for expandability. At the
- moment, each vrl_Surface consists of a type, a hue and a
- brightness. The types are SURF_SIMPLE (no lighting, just a fixed
- color), SURF_FLAT (for flat shading), SURF_GOURAUD (for Gouraud
- shading), SURF_METAL (for a pseudo-metallic effect) and
- SURF_GLASS (for a partially transparent effect). Surfaces are
- initialized and modified using the following routines:
-
- vrl_Surface *vrl_SurfaceInit(vrl_Surface *surf);
- vrl_Surface *vrl_SurfaceCreate(vrl_unsigned8bit hue);
-
- void vrl_SurfaceSetType(vrl_Surface *surf, vrl_LightingType type);
- vrl_LightingType vrl_SurfaceGetType(vrl_Surface *surf);
-
-
- AVRIL Technical Reference Manual 17
-
-
-
-
-
- void vrl_SurfaceSetHue(vrl_Surface *surf, unsigned char h);
- unsigned char vrl_SurfaceGetHue(vrl_Surface *surf);
-
- void vrl_SurfaceSetBrightness(vrl_Surface *surf, unsigned char b);
- unsigned char vrl_SurfaceGetBrightness(vrl_Surface *surf);
-
- The hue and brightness values are 8-bit unsigned quantities; the
- maximum brightness value is therefore 255.
-
- Future versions of AVRIL may support specular shading; the
- following two functions allow you to set and get the specular
- exponent value, which controls the "sharpness" of the specular
- highlights:
-
- void vrl_SurfaceSetExponent(vrl_Surface *surf, vrl_Exponent exp);
- vrl_Exponent vrl_SurfaceGetExponent(vrl_Surface *surf);
-
- For backwards compatibility with REND386, AVRIL includes
- functions to convert a 16-bit REND386 surface descriptor into a
- vrl_Surface, and vice-versa:
-
- vrl_Surface *vrl_SurfaceFromDesc(vrl_unsigned16bit desc, vrl_Surface *surf);
- vrl_unsigned16bit vrl_SurfaceToDesc(vrl_Surface *surf);
-
- As surfaces are created, they are added to a list; the following
- functions allow you to iterate through the list:
-
- vrl_Surface *vrl_SurfaceGetList(void);
- vrl_Surface *vrl_SurfaceGetNext(vrl_Surface *surf);
-
- Surface Maps
-
- Surface maps contain an array of pointers to surfaces; you
- can create a surface map with room for a particular number of
- entries, find out how many entries the map contains, and access
- entries within a map, using the following routines:
-
- vrl_Surfacemap *vrl_SurfacemapCreate(int n);
- int vrl_SurfacemapCountEntries(vrl_Surfacemap *map);
- vrl_Surface *vrl_SurfacemapGetSurface(vrl_Surfacemap *map, int surfnum);
- vrl_Surface *vrl_SurfacemapSetSurface(vrl_Surfacemap *map, int surfnum,
- vrl_Surface *surface);
-
- As surfacemaps are defined, they are added to a list; the list
- can be iterated through using the following functions:
-
- vrl_Surfacemap *vrl_SurfacemapGetList(void);
- vrl_Surfacemap *vrl_SurfacemapGetNext(vrl_Surfacemap *map);
-
-
-
-
-
- AVRIL Technical Reference Manual 18
-
-
-
-
-
- Lights
-
- Lights in AVRIL have a number of properties; they can be on
- or off, they can have an intensity, they can have a "type", and
- they can be associated with an object. The on/off and intensity
- properties are similar to a household dimmer; rotating the knob
- on a dimmer alters the intensity, and pushing it in toggles the
- light on and off.
-
- The current version of AVRIL only supports ambient lights
- and directional lights; point sources will be supported soon.
- Any light that is not associated with an object is considered
- ambient; this is in addition to the overall ambient light level
- for the world. A directional light uses the orientation of the
- object it's associated with to determine which direction the
- light should come from. A point source light (once implemented)
- will use the location of the object it's associated with to
- determine where the light comes from.
-
- As with worlds and objects, lights can be statically or
- dynamically created and destroyed using the following functions:
-
- vrl_Light *vrl_LightInit(vrl_Light *light);
- vrl_Light *vrl_LightCreate(void);
- void vrl_LightDestroy(vrl_Light *light);
-
- The light's type value can be one of LIGHT_AMBIENT,
- LIGHT_DIRECTIONAL or LIGHT_POINTSOURCE, and is set and queried
- using the following two functions:
-
- void vrl_LightSetType(vrl_Light *light, int type);
- int vrl_LightGetType(vrl_Light *light);
-
- The light's on/off status can be checked and altered, and the
- intensity set and queried, using these functions:
-
- void vrl_LightOn(vrl_Light *light);
- void vrl_LightOff(vrl_Light *light);
- void vrl_LightToggle(vrl_Light *light);
- vrl_Boolean vrl_LightIsOn(vrl_Light *light);
-
- void vrl_LightSetIntensity(vrl_Light *light, vrl_Factor inten);
- vrl_Factor vrl_LightGetIntensity(vrl_Light *light);
-
- Notice that the intensity values are vrl_Factors; they should
- never be less than zero or greater than VRL_UNITY.
-
- You can make and break associations between a light source
- and an object, and determine what object a light source is
- currently associated with, using the following routines:
-
- void vrl_LightAssociate(vrl_Light *light, vrl_Object *object);
-
- AVRIL Technical Reference Manual 19
-
-
-
-
-
- void vrl_LightDisAssociate(vrl_Light *light);
- vrl_Object *vrl_LightGetObject(vrl_Light *light);
-
- Many of the routines that were used for objects earlier have
- counterparts that are used for light sources; they're implemented
- as macros that just perform the operations on the object with
- which the light source is associated.
-
- vrl_LightMove(light, x, y, z);
- vrl_LightRelMove(light, x, y, z);
- vrl_LightVectorMove(light, v);
- vrl_LightVectorRelMove(light, v);
- vrl_LightRotX(light, angle);
- vrl_LightRotY(light, angle);
- vrl_LightRotZ(light, angle);
- vrl_LightRotVector(light, angle, vector);
- vrl_LightRotReset(light);
- vrl_LightRotate(light, angle, axis, frame, relative_to);
- vrl_LightTranslate(light, v, axis, frame, relative_to);
- vrl_LightLookAt(light, forward, up);
- vrl_LightAttach(obj, newparent);
- vrl_LightDetach(obj);
- vrl_LightGetWorldX(light);
- vrl_LightGetWorldY(light);
- vrl_LightGetWorldZ(light);
- vrl_LightGetWorldLocation(light, v);
- vrl_LightGetWorldRotations(light, rx, ry, rz);
- vrl_LightGetRelativeX(light);
- vrl_LightGetRelativeY(light);
- vrl_LightGetRelativeZ(light);
- vrl_LightGetRelativeLocation(light, v);
- vrl_LightGetRelativeRotations(light, rx, ry, rz);
-
- It's important to note the difference between attaching and
- associating light sources. A light source can be associated with
- an object, which means it will use that object's location and
- orientation as its own. The object with which the light is
- associated can be attached to another object, and "inherit"
- location and orientation information from it. The
- vrl_LightAttach() and vrl_LightDetach() routines are provided
- only as a convenience; what you're really attaching and detaching
- with those routines is the object that the light is associated
- with. You generally associate a light source with an object
- once, and leave it that way; you can attach or detach the light
- however you want after that.
-
- Lights can have other attributes as well, just as objects
- can; specifically, they can have a name and some application-
- specific data, which are accessed using the following functions:
-
- void vrl_LightSetName(vrl_Light *light, char *str);
- char *vrl_LightGetName(vrl_Light *light);
-
- AVRIL Technical Reference Manual 20
-
-
-
-
-
- void vrl_LightSetApplicationData(vrl_Light *light, void *data);
- void *vrl_LightGetApplicationData(vrl_Light *light);
-
- Cameras
-
- AVRIL allows you to have any number of virtual cameras.
- Each camera is associated with an object, much as lights are.
- However, unlike lights, cameras must be associated with an
- object; there's no such thing as an "ambient" camera. Cameras
- are initialized and destroyed just like objects or light sources:
-
- vrl_Camera *vrl_CameraInit(vrl_Camera *camera);
- vrl_Camera *vrl_CameraCreate(void);
- void vrl_CameraDestroy(vrl_Camera *camera);
-
- Cameras have only a few properties that are important; in
- particular, a zoom factor, an aspect ratio, and hither and yon
- clipping plane distances. These are all set and queried using
- the following routines:
-
- void vrl_CameraSetZoom(vrl_Camera *camera, float zoom);
- float vrl_CameraGetZoom(vrl_Camera *camera);
-
- void vrl_CameraSetAspect(vrl_Camera *camera, float asp);
- float vrl_CameraGetAspect(vrl_Camera *camera);
-
- void vrl_CameraSetHither(vrl_Camera *camera, vrl_Scalar hither);
- vrl_Scalar vrl_CameraGetHither(vrl_Camera *camera);
-
- void vrl_CameraSetYon(vrl_Camera *camera, vrl_Scalar yon);
- vrl_Scalar vrl_CameraGetYon(vrl_Camera *camera);
-
- Notice that the zoom factor and aspect ratio are floats; this may
- change in a future release of AVRIL. The zoom factor works like
- the zoom on a camera; the higher the zoom, the more the image is
- magnified. The zoom is the tangent of half the field of view.
- The aspect ratio is the ratio between the horizontal and vertical
- zoom factors. The hither clipping distance is the distance in
- virtual space from the camera to the invisible plane at which
- objects will be "clipped". The "yon" distance is like an
- invisible wall; any object entirely on the far side of the wall
- will not be seen.
-
- The routines for associating a camera with an object and for
- determining what object a camera is currently associated with are
- as follows:
-
- void vrl_CameraAssociate(vrl_Camera *camera, vrl_Object *object);
- vrl_Object *vrl_CameraGetObject(vrl_Camera *camera);
-
-
-
-
- AVRIL Technical Reference Manual 21
-
-
-
-
-
- There's no vrl_CameraDisAssociate() function, as there was for
- lights; cameras must be associated with an object in order to
- have any meaning.
-
- Again, routines are provided for manipulating and querying
- the location and orientation of a virtual camera; these are
- macros, just as they were for lights:
-
- vrl_CameraMove(camera, x, y, z);
- vrl_CameraRelMove(camera, x, y, z);
- vrl_CameraVectorMove(camera, v);
- vrl_CameraVectorRelMove(camera, v);
- vrl_CameraRotX(camera, angle);
- vrl_CameraRotY(camera, angle);
- vrl_CameraRotZ(camera, angle);
- vrl_CameraRotVector(camera, angle, vector);
- vrl_CameraRotReset(camera);
- vrl_CameraRotate(camera, angle, axis, frame, relative_to);
- vrl_CameraLookAt(camera, forward, up);
- vrl_CameraTranslate(camera, v, axis, frame, relative_to);
- vrl_CameraAttach(obj, newparent);
- vrl_CameraDetach(obj);
- vrl_CameraGetWorldX(camera);
- vrl_CameraGetWorldY(camera);
- vrl_CameraGetWorldZ(camera);
- vrl_CameraGetWorldLocation(camera, v);
- vrl_CameraGetWorldRotations(camera, rx, ry, rz);
- vrl_CameraGetRelativeX(camera);
- vrl_CameraGetRelativeY(camera);
- vrl_CameraGetRelativeZ(camera);
- vrl_CameraGetRelativeLocation(camera, v);
- vrl_CameraGetRelativeRotations(camera, rx, ry, rz);
-
- Camera can have other attributes as well, just as objects and
- lights can; specifically, they can have a name and some
- application-specific data, which are accessed using the following
- functions:
-
- void vrl_CameraSetName(vrl_Camera *camera, char *str);
- char *vrl_CameraGetName(vrl_Camera *camera);
- void vrl_CameraSetApplicationData(vrl_Camera *camera, void *data);
- void *vrl_CameraGetApplicationData(vrl_Camera *camera);
-
- In addition, there are three routines that obtain the current
- "forward", "right" and "up" vectors for a camera:
-
- vrl_CameraGetForwardVector(camera, v)
- vrl_CameraGetRightVector(camera, v)
- vrl_CameraGetUpVector(camera, v)
-
-
-
-
- AVRIL Technical Reference Manual 22
-
-
-
-
-
- Layers
-
- Layers were described earlier, in the section on objects.
- The routines for dealing with layers are as follows:
-
- void vrl_LayerOn(int n);
- void vrl_LayerOff(int n);
- void vrl_LayerToggle(int n);
- int vrl_LayerIsOn(int n);
- void vrl_LayerAllOn(void);
- void vrl_LayerAllOff(void);
-
- The last two routines, vrl_LayerAllOn() and vrl_LayerAllOff(),
- turn all the layers on or off at once. By default, all layers
- are on.
-
- Stereoscopic Rendering
-
- Stereoscopic rendering consists of generating two images, one for
- the left eye and one for the right. The world data structure
- maintains a flag indicating whether stereoscopic rendering should
- be used, as well as pointers to the left-eye and right-eye
- cameras and the stereo configuration information; see the section
- on Worlds for more information.
-
- There are a number of ways of transferring the separate left and
- right images to the viewer's eyes; among them are anaglyph
- techniques that use red and blue filters, field sequential
- techniques that use shutter glasses, optical techniques that use
- a split screen, alternate-scanline techniques, and systems that
- use more than one VGA card.
-
- In addition, there are systems that provide stereoscopic depth
- without using separate images: the patented "Chromadepth"
- technique used in some comic books and laser light shows is one,
- and SIRDS (Single-Image Random Dot Stereograms, or "Magic Eye"
- pictures) are another.
-
- In AVRIL, information about the current stereo configuration is
- stored in a structure of type vrl_StereoConfiguration. Such a
- structure can be created (or initialized) using the following
- functions:
-
- vrl_StereoConfiguration *vrl_StereoCreateConfiguration(void);
- vrl_StereoConfiguration *vrl_StereoInitConfiguration(vrl_StereoConfiguration *conf);
-
- The type of stereoscopic viewing is defined by a constant; the
- possible values are listed in Appendix I. Setting and getting
- the type of stereoscopic viewing is done using the following
- functions:
-
- void vrl_StereoSetType(vrl_StereoConfiguration *conf, vrl_StereoType st_type);
-
- AVRIL Technical Reference Manual 23
-
-
-
-
-
- vrl_StereoType vrl_StereoGetType(vrl_StereoConfiguration *conf);
-
- Some systems, like Chromadepth and SIRDS, use a single "eye";
- most others use two eyes. There's a function for determining the
- number of "eyes" used by the current stereo type:
-
- int vrl_StereoGetNeyes(vrl_StereoConfiguration *conf);
-
- You can alter the amount by which each eye's image is shifted on
- the screen using the following functions:
-
- void vrl_StereoSetLeftEyeShift(vrl_StereoConfigurtion *conf, int shift);
- int vrl_StereoGetLeftEyeShift(vrl_StereoConfigurtion *conf);
- void vrl_StereoSetRightEyeShift(vrl_StereoConfigurtion *conf, int shift);
- int vrl_StereoGetRightEyeShift(vrl_StereoConfigurtion *conf);
-
- This shift is necessary, due to differences between HMDs. The
- total shift (the sum of that which is computed and that which is
- explicitly set by the functions above) can be obtained using the
- following functions:
-
- int vrl_StereoGetTotalLeftShift(vrl_StereoConfiguration *conf);
- int vrl_StereoGetTotalRightShift(vrl_StereoConfiguration *conf);
-
- It may be necessary, because of the way an HMD's optics are
- constructed, to rotate the virtual eyes inwards or outwards.
- This is done using the following functions:
-
- void vrl_StereoSetLeftEyeRotation(vrl_StereoConfiguration *conf, vrl_Angle rot);
- vrl_Angle vrl_StereoGetLeftEyeRotation(vrl_StereoConfiguration *conf);
- void vrl_StereoSetRightEyeRotation(vrl_StereoConfiguration *conf, vrl_Angle rot);
- vrl_Angle vrl_StereoGetRightEyeRotation(vrl_StereoConfiguration *conf);
-
- The eye spacing and convergence distance (both in world units)
- can be manipulated using the following functions:
-
- void vrl_StereoSetEyespacing(vrl_StereoConfiguration *conf, float spacing);
- float vrl_StereoGetEyespacing(vrl_StereoConfiguration *conf);
- void vrl_StereoSetConvergence(vrl_StereoConfiguration *conf, float conv);
- float vrl_StereoGetConvergence(vrl_StereoConfiguration *conf);
-
- By using various values for eyespacing and convergence distance,
- a strong or weaker stereo effect can be achieved.
-
- The Chromadepth technique is unusual, in that it uses distance to
- compute a color between extreme red and extreme blue. Since only
- a finite number of palette entries is available, it's necessary
- to optimize their use over a range of distance; this range is
- represented by the "ChromaNear" and "ChromaFar" values, which can
- be altered using the following functions:
-
- void vrl_StereoSetChromaNear(vrl_StereoConfiguration *conf, vrl_Scalar val);
-
- AVRIL Technical Reference Manual 24
-
-
-
-
-
- vrl_Scalar vrl_StereoGetChromaNear(vrl_StereoConfiguration *conf);
- void vrl_StereoSetChromaFar(vrl_StereoConfiguration *conf, vrl_Scalar val);
- vrl_Scalar vrl_StereoGetChromaFar(vrl_StereoConfiguration *conf);
-
- After altering any of the values in a vrl_StereoConfiguration
- structure, the following function should be called:
-
- int vrl_StereoConfigure(vrl_StereoConfiguration *conf);
-
- In order for the system to render a scene stereoscopically, both
- the left-eye and right-eye cameras must exist in the current
- world; to create them initially, use the following function:
-
- int vrl_StereoSetup(void); /* creates a pair of cameras */
-
- There are a number of routines in the scan-conversion module
- (i.e., the display driver) that relate to stereoscopic viewing;
- they are described in the section on display drivers.
-
- For more information about stereoscopic rendering and its
- implementation, see the source code in system.c (which makes all
- the appropriate calls).
-
- File I/O Routines
-
- AVRIL supports the PLG file format, the FIG file format, and
- most of the WLD file format; these formats are described in the
- Appendices. The library contains routines for reading each of
- those formats:
-
- vrl_Shape *vrl_ReadPLG(FILE *in);
- vrl_Object *vrl_ReadObjectPLG(FILE *in);
- int vrl_ReadWLD(FILE *in);
- vrl_Object *vrl_ReadFIG(FILE *in, vrl_Object *parent, char *rootname);
-
- The vrl_ReadPLG() routine reads a shape from the specified file
- and returns a pointer to it. The vrl_ReadObjectPLG() routine is
- similar, but it also allocates an object and assigns the shape to
- it.
-
- The vrl_ReadWLD() function reads a world description from
- the file into the current world; you can make as many calls to
- this routine as you like, combining a number of WLD files. While
- reading a WLD file, statements may be encountered which the WLD
- parser doesn't recognize; these are passed to an application-
- defined function called
-
- void vrl_ReadWLDfeature(int argc, char *argv[], char *rawtext);
-
- The argc and argv[] parameters are just like the ones passed to a
- main() function in C; the rawtext parameter is the original input
- line.
-
- AVRIL Technical Reference Manual 25
-
-
-
-
-
- The vrl_ReadFIG() routine lets you specify a "parent" object
- to which the newly-read object tree should be attached, as well
- as the name of the root object. Any segment names (segnames)
- that are assigned in the FIG file will be added to the current
- world's list of objects as rootname.segname.
-
- All the routines listed above assume you've already opened
- the file; there are also routines for loading objects, figures
- and entire worlds from files, given the filename:
-
- vrl_Object *vrl_ObjectLoadPLGfile(char *filename);
- vrl_Object *vrl_ObjectLoadFIGfile(char *filename);
- int *vrl_LoadWLDfile(char *filename);
-
- While loading a PLG file, a scale factor and offset can be
- applied. The vertices read from the file are multiplied by the
- scaling factors, and then the offsets are added to them. The
- scale factors and offsets are set using:
-
- void vrl_SetReadPLGscale(float x, float y, float z);
- void vrl_SetReadPLGoffset(float x, float y, float z);
-
- FIG files can also have a scale factor applied to them. In
- addition, parts of a figure that have a "segnum" value set can
- have pointers to their objects placed into a parts array
- specified by the user:
-
- void vrl_SetReadFIGscale(float x, float y, float z);
- void vrl_SetReadFIGpartArray(vrl_Object **ptr, int maxparts);
-
- If the ptr is not NULL, then any parts in the FIG file that have
- a segnum will create an entry in the array, indexed by the segnum
- value. The maxparts value is the number of elements the caller
- has provided space for in the array.
-
- There are several other routines that support file
- operations. Two routines maintain a kind of "current directory"
- for file loading; they are
-
- void vrl_FileSetLoadpath(char *path);
- char *vrl_FileFixupFilename(char *fname);
-
- The first sets the given path (if not NULL) to be the directory
- that subsequent filename fixups should use. The second routine
- is used to generate a full filename, with the current loadpath
- prepended. Note that filenames beginning with '/' or '\' are not
- modified. Also note that vrl_FileFixupFilename() returns a
- pointer to an internal buffer, which will be rewritten on the
- next call to vrl_FileFixupFilename(). If you really need to keep
- the fixed-up filename around, you should strcpy() it to another
- buffer or strdup() it.
-
-
- AVRIL Technical Reference Manual 26
-
-
-
-
-
- System and Application routines
-
- These routines are described in detail in the Tutorial, but
- here's a quick summary:
-
- vrl_Boolean vrl_SystemStartup(void);
- void vrl_SystemRun(void);
- vrl_RenderStatus *vrl_SystemRender(vrl_Object *list);
- vrl_Time vrl_SystemGetRenderTime(void);
- vrl_Time vrl_SystemGetFrameRate(void);
- void vrl_SystemCommandLine(int argc, char *argv[]);
-
- void vrl_SystemRequestRefresh(void);
- vrl_Boolean vrl_SystemQueryRefresh(void);
-
- void vrl_SystemStartRunning(void);
- void vrl_SystemStopRunning(void);
- vrl_Boolean vrl_SystemIsRunning(void);
-
- void vrl_ApplicationDrawUnder(void);
- void vrl_ApplicationDrawOver(vrl_RenderStatus *stat);
- void vrl_ApplicationInit(void);
- void vrl_ApplicationKey(vrl_unsigned16bit c);
- void vrl_ApplicationMouseUp(int x, int y, unsigned int buttons);
-
- These are not really part of AVRIL's "guts", since you don't need
- to use anything in system.c (which is the only module that knows
- about the vrl_Application functions).
-
- User Interface
-
- The current version of AVRIL has a few primitive user
- interface routines for you to use. A better user interface needs
- to be designed; in the meantime, here are the routines:
-
- void vrl_UserInterfaceBox(int width, int height, int *x, int *y);
- void vrl_UserInterfacePopMsg(char *msg);
- void vrl_UserInterfacePopText(char *text[]);
- int vrl_UserInterfaceDismiss(void);
- int vrl_UserInterfacePopMenu(char *text[]);
- int vrl_UserInterfaceMenuDispatch(char *text[], int (**funcs)(void));
- vrl_unsigned16bit vrl_UserInterfacePopPrompt(char *prompt, char *buff, int n);
-
- The vrl_UserInterfaceBox() routine puts up a nice bordered box,
- centered on the screen. The width and height determine the size
- of the box. When the routine returns, x and y will contain the
- screen coordinates of the top-left corner of the box. Either can
- be NULL, indicating that you don't care about the values.
-
- The vrl_UserInterfacePopMsg() routine displays a one-line
- text message. The vrl_UserInterfacePopText() routine puts up a
-
-
- AVRIL Technical Reference Manual 27
-
-
-
-
-
- multi-line message; the array of string pointers has to have a
- NULL pointer entry at the end.
-
- The vrl_UserInterfaceDismiss() routine is useful after
- you've called either vrl_UserInteracePopMsg() or
- vrl_UserInterfacePopText(); it waits for the user to press a key
- or click the mouse.
-
- The vrl_UserInterfacePopMenu() routine displays a menu and
- waits for the user to select an item. If the user clicks on an
- item with the mouse, the index of that item will be returned as
- the value of the function. If the user presses a key, the menu
- is searched item by item until one is found that has an uppercase
- letter matching the key the user entered; the index of that entry
- is returned. If the user clicks outside the menu, or presses
- ESC, the value -1 is returned.
-
- The vrl_UserInterfaceMenuDispatch() routine is similar to
- vrl_UserInterfacePopMenu(), but it takes an array of pointers to
- functions as a second parameter. When an item in the menu is
- selected, the corresponding function is called. No parameters
- are passed to that function.
-
- The vrl_UserInterfacePopPrompt() box displays a prompt to
- the user and lets them enter a text response. The backspace key
- is supported. The user can end their input using either ENTER or
- ESC; the key they press to end their input is returned as the
- value of the function.
-
- There are two other routines which are not really part of
- the user interface; they're used to overlay text on the screen or
- display the compass. They're typically called from
- vrl_ApplicationDrawOver().
-
- void vrl_UserInterfaceDrawCompass(vrl_Camera *camera, int x, int y, int armlen);
- void vrl_UserInterfaceDropText(int x, int y, vrl_Color, char *text);
-
- In vrl_UserInterfaceDrawCompass(), the x and y values are the
- location of the "origin" of the compass and armlen is the length
- of each arm. (The arms will of course seem shorter because of
- perspective). The x, y and armlen values are in screen
- coordinates (i.e., pixels). The camera is used to obtain
- orientation information about the user's viewpoint.
-
- The vrl_UserInterfaceDropText() routine displays the text
- message at the given screen coordinates in the given color, with
- a black (i.e., color 0) drop shadow.
-
-
-
-
-
-
- AVRIL Technical Reference Manual 28
-
-
-
-
-
- Tasks
-
- The pseudo-tasking mechanism is described in the Tutorial.
- Tasks are added using vrl_TaskCreate(), which takes a pointer to
- the function, a pointer to the data, and the period. The tasks
- should be run periodically by calling vrl_TaskRun(), which is
- normally done in vrl_SystemRun(). The tasks can obtain a pointer
- to their data by calling vrl_TaskGetData(), the elapsed time
- since they last ran by calling vrl_TaskGetElapsed(), and the
- current time by calling vrl_TaskGetTimeNow(). Note that for any
- given call to vrl_TaskRun(), all the tasks will receive the same
- value from vrl_TaskGetTimeNow(); this is different from
- vrl_TimerRead(), since the timer runs independently of the tasks.
- You may want to use one or the other of those two functions
- depending on the circumstances.
-
- vrl_Boolean vrl_TaskCreate(void (*function)(void), void *data, vrl_Time period);
- void vrl_TaskRun(void);
- void *vrl_TaskGetData(void);
- vrl_Time vrl_TaskGetElapsed(void);
- vrl_Time vrl_TaskGetTimeNow(void);
-
- Primitives
-
- AVRIL currently provides five utility routines for creating
- simple geometric primitives. Each takes a surface map pointer;
- if the value is NULL, the default color for geometric primitives
- is used.
-
- vrl_Shape *vrl_PrimitiveBox(vrl_Scalar width, vrl_Scalar height, vrl_Scalar depth,
- vrl_Surfacemap *map);
-
- vrl_Shape *vrl_PrimitiveCone(vrl_Scalar radius, vrl_Scalar height, int nsides,
- vrl_Surfacemap *map);
-
- vrl_Shape *vrl_PrimitiveCylinder(vrl_Scalar bottom_radius, vrl_Scalar top_radius,
- vrl_Scalar height, int nsides, vrl_Surfacemap *map);
-
- vrl_Shape *vrl_PrimitivePrism(vrl_Scalar width, vrl_Scalar height, vrl_Scalar depth,
- vrl_Surfacemap *map);
-
- vrl_Shape *vrl_PrimitiveSphere(vrl_Scalar radius, int vsides, int hsides,
- vrl_Surfacemap *map);
-
- The box and sphere have their origin at their geometric centers,
- the cone and the cylinder have their origin at the center of
- their bases, and the prism has its origin at one corner. You can
- use vrl_ShapeOffset() to change these choices if you wish.
-
-
-
-
-
- AVRIL Technical Reference Manual 29
-
-
-
-
-
- Rendering
-
- The rendering "engine" needs to be initialized before any
- actual rendering is done. The renderer needs to know how much
- memory to allocate for itself, as well as the maximum number of
- objects, facets, vertices and lights it will have to contend
- with. When the program is ready to exit, vrl_RenderQuit() should
- be called to cleanly shut down the engine.
-
- vrl_Boolean vrl_RenderInit(int maxvert, int maxf, int maxobjs, int maxlights,
- unsigned int mempoolsize);
- void vrl_RenderQuit(void);
-
- The routines in system.c normally handle the calling of
- vrl_RenderInit(), and the setting up of an atexit() function for
- vrl_RenderQuit().
-
- Two functions are used to give the renderer a pointer to the
- current camera and list of lights, and to set the current ambient
- lighting level (usually that for the current world):
-
- void vrl_RenderBegin(vrl_Camera *camera, vrl_Light *lights);
- void vrl_RenderSetAmbient(vrl_Factor amb);
-
- Finally, two functions do the actual drawing; one draws a
- horizon, the other renders a list of objects (such as that
- returned by vrl_ObjectUpdate() or vrl_WorldUpdate()).
-
- void vrl_RenderHorizon(void);
- vrl_Status *vrl_RenderObjlist(vrl_Object *objects);
-
- The vrl_RenderObjlist() function returns a pointer to a status
- struct, which is described in the Tutorial.
-
- Since the renderer can highlight objects and draw them in
- wireframe, there are functions for setting and getting the colors
- used for highlighting and wireframe:
-
- void vrl_RenderSetWireframeColor(vrl_Color color);
- vrl_Color vrl_RenderGetWireframeColor(void);
- void vrl_RenderSetHighlightColor(vrl_Color color);
- vrl_Color vrl_RenderGetHighlightColor(void);
-
- You can also set and get the rendering mode:
-
- void vrl_RenderSetDrawMode(int mode);
- int vrl_RenderGetDrawMode(void);
-
- At the moment, the only values supported for the mode are 0
- (normal) and 1 (wireframe).
-
-
-
- AVRIL Technical Reference Manual 30
-
-
-
-
-
- For stereoscopic rendering, a horizontal shift factor is
- required:
-
- void vrl_RenderSetHorizontalShift(int npixels);
-
- There are two functions that allow you to monitor a particular
- point on the screen, render the world, and then see what objects
- and facets were under the cursor (and nearest the viewer).
-
- void vrl_RenderMonitorInit(int x, int y);
- vrl_Boolean vrl_RenderMonitorRead(vrl_Object **obj, vrl_Facet **facet, int *vertnum);
-
- The x and y values are coordinates in the current screen window
- (such as those passed to vrl_ApplicationMouseUp()). The obj
- pointer (if not NULL) gets set to point to the object the cursor
- was over; similarly, the facet pointer (if not NULL) gets set to
- point to the facet the cursor was over. The vertnum pointer is
- not currently used. If nothing was under the cursor,
- vrl_RenderMonitorRead() returns zero. Remember that you must
- call vrl_RenderObjlist() between the call to
- vrl_RenderMonitorInit() and vrl_RenderMonitorRead(); typically,
- you would call it as vrl_RenderObjlist(NULL) to just re-render
- the last object list that was used.
-
- If you need to find out where on the screen a specific
- vertex will be drawn, you can use the following function:
-
- void vrl_TransformVertexToScreen(vrl_ScreenCoord *x, vrl_ScreenCoord *y, vrl_Object *obj,
- vrl_Vector vertex);
-
- The vertex is assumed to be in the object's coordinate system.
- The vertex is transformed, projected, scaled and shifted and the
- screen coordinates are stored in x and y. Note that the values
- are of type vrl_ScreenCoord, so you should right shift the
- results by VRL_SCREEN_FRACT_BITS. The vrl_ObjectToScreen()
- function uses information computed during the most recent call to
- vrl_RenderBegin(), so the values will not reflect any changes
- made since then.
-
- The Timer
-
- AVRIL has a set of routines which deal with the timer; these
- will vary from one platform to another, but they should all
- provide the same high-level interface to application software.
-
- vrl_Boolean vrl_TimerInit(void);
- void vrl_TimerQuit(void);
- vrl_Time vrl_TimerRead(void);
- vrl_Time vrl_TimerGetTickRate(void);
- void vrl_TimerDelay(vrl_Time milliseconds);
-
-
-
- AVRIL Technical Reference Manual 31
-
-
-
-
-
- These routines let you initialize, de-initialize and read the
- timer. The vrl_TimerGetTickRate() routine returns the number of
- ticks per second that the timer runs at. The higher this number
- is, the more accurate the frames/second calculations will be
- (among other things). It is expected that all future versions of
- AVRIL will use 1000 ticks per second, so that each tick is one
- millisecond; however, to be on the safe side, always use
- vrl_TimerGetTickRate().
-
- The Mouse
-
- Like the timer routines, the mouse routines will differ from
- platform to platform, but the high-level interface should remain
- the same.
-
- vrl_Boolean vrl_MouseInit(void);
- void vrl_MouseQuit(void);
- vrl_Boolean vrl_MouseReset(void);
- vrl_Boolean vrl_MouseRead(int *x, int *y, unsigned int *buttons);
- void vrl_MouseSetUsage(int u);
- int vrl_MouseGetUsage(void);
- void vrl_MouseSetPointer(void *u);
- void *vrl_MouseGetPointer(void);
-
- These routines let you initialize and read the mouse. Since the
- mouse can be used either as a screen-oriented pointer or as a 6D
- input device (see the Devices section), there has to be some way
- of toggling between those two functions. That's what the
- vrl_MouseSetUsage() and vrl_MouseGetUsage() functions are for; a
- non-zero value means the mouse is a 6D device, a zero value means
- it's a screen pointer.
-
- When the mouse is a 6D device, it's useful to be able to
- obtain a pointer to the vrl_Device which is using it; similarly,
- the vrl_Device function (described later) must be able to set
- that pointer. That's what the vrl_MouseSetPointer() and
- vrl_MouseGetPointer() calls do; they set and get a pointer to the
- vrl_Device that's using the mouse for 6D input.
-
- The Keyboard
-
- Like the timer and the mouse, the keyboard routines will be
- implemented very differently on different platforms, but they
- should provide a consistent high-level interface.
-
- vrl_Boolean vrl_KeyboardCheck(void);
- unsigned int vrl_KeyboardRead(void);
-
- The vrl_KeyboardCheck() routine returns non-zero if a key has
- been pressed, and vrl_KeyboardRead() returns the actual key.
- Most keys just return their ASCII values; see the file avrilkey.h
-
-
- AVRIL Technical Reference Manual 32
-
-
-
-
-
- for definitions of special keys (like arrows, function keys,
- etc).
-
- Memory Allocation Routines
-
- AVRIL has three functions which are (at the moment) just wrappers
- around the standard malloc(), calloc() and free() functions. You
- should always use these functions rather than the system
- equivalents, for compatability with future versions of AVRIL.
-
- void *vrl_malloc(unsigned int nbytes);
- void *vrl_calloc(unsigned int nitems, unsigned int item_size);
- void vrl_free(void *ptr);
-
- Raster Routines
-
- AVRIL uses the notion of a "raster", a rectangular array of pixel
- values. In most cases, all rendering is done into a raster,
- which may or may not correspond to an actual physical screen; in
- cases where it doesn't, it's necessary to copy ("blit") the
- raster to the display.
-
- Each raster has a height, a width, a depth (number of bits per
- pixel) a window (the rectangular region within the raster into
- which rendering is done) and a "rowbytes" value (the number of
- bytes per horizontal row of pixels).
-
- The following routines are used to deal with rasters:
-
- vrl_Raster *vrl_RasterCreate(vrl_ScreenPos width, vrl_ScreenPos height,
- vrl_unsigned16bit depth);
- void vrl_RasterDestroy(vrl_Raster *raster);
- void vrl_RasterSetWindow(vrl_Raster *raster,
- vrl_ScreenPos left, vrl_ScreenPos top, vrl_ScreenPos right, vrl_ScreenPos bottom);
- void vrl_RasterGetWindow(vrl_Raster *raster, vrl_ScreenPos *left, vrl_ScreenPos *top,
- vrl_ScreenPos *right, vrl_ScreenPos *bottom);
- vrl_ScreenPos vrl_RasterGetHeight(vrl_Raster *r);
- vrl_ScreenPos vrl_RasterGetWidth(vrl_Raster *r);
- vrl_ScreenPos vrl_RasterGetDepth(vrl_Raster *r);
- vrl_ScreenPos vrl_RasterGetRowbytes(vrl_Raster *r);
- void vrl_RasterSetRowbytes(vrl_Raster *r, vrl_ScreenPos n);
-
- The reason for setting the number of bytes per row of pixels has
- to do with alternate scan-line encoding; if you render the left
- and right images into the left and right halves of a 640-pixel
- wide screen, and then set the rowbytes value to 320, you wind up
- with a raster that has the left-eye image on the even scanlines
- and the right-eye image on the odd scanlines.
-
- You can read scanlines from a raster into a buffer, or write them
- from a buffer into the raster. You can also obtain a pointer to
-
-
- AVRIL Technical Reference Manual 33
-
-
-
-
-
- the actual data for the raster (i.e. the raw array of pixel
- values).
-
- void vrl_RasterReadScanline(vrl_Raster *r, int n, unsigned char *buff);
- void vrl_RasterWriteScanline(vrl_Raster *r, int n, unsigned char *buff);
- unsigned char *vrl_RasterGetData(vrl_Raster *r);
-
- Even though you can obtain a pointer to the actual data, it's
- generally a bad idea to do anything with it.
-
- Palettes and Huemaps
-
- AVRIL makes use of a "palette", a collection of (up to) 256
- colors. Each of those colors has three 8-bit components -- one
- for red, one for green and one for blue. On the PC's VGA card,
- only 6 bits are actually used for each component.
-
- The vrl_Color values that AVRIL uses are (in a paletted
- implementation) used to index the palette to select an actual
- color. In order to do shading of facets and vertices, AVRIL
- divides the palette into a number of "hues", with a number of
- shades for each hue. By default, the first 16 entries of the
- 256-color palette are simple non-shaded colors (for use in menus
- and overlaid text); the remaining 240 colors are treated as 15
- hues with 16 shades each.
-
- However, this is not etched in stone. AVRIL supports the use of
- a "hue map", which relates a hue index to a start color in the
- palette and a count of the number of shades. For example, by
- using the hue map, you could choose to have 64 shades of flesh
- tone (instead of 16) in order to represent human beings more
- accurately.
-
- A hue is represented by a vrl_Hue type, and a palette by a
- vrl_Palette type. Palettes have a flag that indicates that
- they've been changed; this is important, since it forces the
- system to update the physical palette stored in the video
- hardware.
-
- The following functions will initialize a palette, read a palette
- and huemap data from a file, get and set individual entries in
- the palette, get a pointer to a palette's huemap, and read and
- check the "changed" status of the palette:
-
- void vrl_PaletteInit(vrl_Palette *pal);
- int vrl_PaletteRead(FILE *in, vrl_Palette *pal);
- vrl_Color vrl_PaletteGetEntry(vrl_Palette *pal, int n);
- void vrl_PaletteSetEntry(vrl_Palette *pal, int n, vrl_Color color);
- vrl_Boolean vrl_PaletteHasChanged(vrl_Palette *pal);
- void vrl_PaletteSetChanged(vrl_Palette *pal, vrl_Boolean flag);
- vrl_Hue *vrl_PaletteGetHuemap(vrl_Palette *pal);
-
-
- AVRIL Technical Reference Manual 34
-
-
-
-
-
- Each world structure has a palette built into it; you can obtain
- a pointer to it using the following function:
-
- vrl_Palette *vrl_WorldGetPalette(void);
-
- Bear in mind that the palettes we're discussing here are
- independent of the actual, physical palette that's maintained by
- the video hardware; see the section on Video routines for more
- information about the hardware palette.
-
- Video Routines
-
- AVRIL takes care of all the "high-level" functions required
- of a VR library, including the handling of input devices, reading
- files, maintaining data structures, doing transforms and lighting
- calculations and so on. AVRIL makes calls to lower-level
- routines to do things like accessing the display device; in fact,
- it has two separate levels of interface to the display hardware.
-
- The lowest-level display interface is the video driver. The
- video driver is responsible for such things as entering and
- exiting graphics mode, hiding and displaying the cursor and
- loading the hardware palette. Video drivers are easy to replace,
- and you can write your own to support whatever graphics modes you
- wish to use.
-
- Internally, the video driver is just a function; see
- Appendix G for information about how to write one. The
- application-visible functions that access that driver are
- described here.
-
- void vrl_VideoSetDriver(vrl_VideoDriverFunction driver);
-
- This function sets the video driver function to use; all
- subsequent calls to the vrl_Video family of routines will
- ultimately be passed to the specified function. See Appendix G
- for more details.
-
- int vrl_VideoGetVersion(void);
- char *vrl_VideoGetDescription(void);
-
- These two functions allow you to find out which version of the
- video driver specification the currently-selected driver
- supports, and to get a textual description of the driver.
-
- int vrl_VideoSetup(int mode);
- int vrl_VideoGetMode(void);
-
- The vrl_VideoSetup() function puts the system into graphics mode;
- the mode parameter specifies the graphics submode to use (for
- drivers that support multiple graphics modes). The meaning of
- the mode parameter is specific to the driver being used; 0x1234
-
- AVRIL Technical Reference Manual 35
-
-
-
-
-
- may mean completely different things to different video drivers.
- The function returns a non-zero value if it was unable to enter
- the specified graphics mode. The vrl_VideoGetMode() function
- returns the current graphics mode; this may or may not be the one
- that was requested.
-
- void vrl_VideoShutdown(void);
-
- This function shuts down the video subsystem and returns the
- hardware to whatever mode it was in prior to the last call to
- vrl_VideoSetup().
-
- The video subsystem provides a vrl_Raster describing the
- actual physical framebuffer. To obtain a pointer to the raster
- (from which information such as the height, width and depth of
- the video adapter may be obtained), use the following function:
-
- vrl_Raster *vrl_VideoGetRaster(void);
-
- Many video adapters support multiple pages. AVRIL has the notion
- of a "current drawing page" (to which all output is written) and
- a "current view page" (the one that's being displayed on the
- physical screen). The following functions allow you to find out
- how many pages the adapter has, and to set and query the value of
- each of those pages:
-
- int vrl_VideoGetNpages(void);
- void vrl_VideoSetDrawPage(int page);
- int vrl_VideoGetDrawPage(void);
- void vrl_VideoSetViewPage(int page);
- int vrl_VideoGetViewPage(void);
-
- Most current video adapters have 8 bits per pixel, and a
- "palette" of 256 colors. You can find out whether the video
- adapter being used has a palette by using the function
-
- vrl_Boolean vrl_VideoHasPalette(void);
-
- You can read and write a range of values within the palette using
- the following functions:
-
- void vrl_VideoSetPalette(int start, int end, vrl_Palette *palette);
- void vrl_VideoGetPalette(int start, int end, vrl_Palette *palette);
-
- On some systems, you actually render to an off-screen vrl_Raster
- in system memory and then copy (or "blit") the image onto the
- screen. This is done by the function
-
- void vrl_VideoBlit(vrl_Raster *raster)
-
-
-
-
- AVRIL Technical Reference Manual 36
-
-
-
-
-
- You may only want to update the physical display during the
- vertical blanking interval; to monitor the vertical retrace, use
- the following function:
-
- vrl_Boolean vrl_VideoCheckRetrace(void);
-
- The video subsystem is responsible for the on-screen cursor. The
- following functions allow you to hide the cursor, show it again,
- reset it to its initial state, move it and set its appearance:
-
- void vrl_VideoCursorHide(void);
- void vrl_VideoCursorShow(void);
- void vrl_VideoCursorReset(void);
- void vrl_VideoCursorMove(vrl_ScreenPos x, vrl_ScreenPos y);
- void vrl_VideoCursorSetAppearance(void *app);
-
- Whenever you write to the currently visible page (the viewpage)
- you should first call vrl_VideoCursorHide() to prevent the mouse
- from being "squashed" under a falling polygon. When you're
- finished updating the display, call vrl_VideoCursorShow() to let
- the rodent run free again. The vrl_SystemRender() routine, found
- in system.c, shows how these routines are used. The user
- interface routines do the calls to vrl_VideoCursorHide() and
- vrl_VideoCursorShow(), so you don't need to worry about them when
- you use those functions.
-
- Note that the system keeps a count of the number of times
- you've called vrl_VideoCursorHide() and vrl_VideoCursorShow();
- for example, if you hide the mouse cursor twice, you have to show
- it twice before it actually appears. The vrl_VideoCursorReset()
- routine resets the "hidden" count.
-
- The vrl_VideoCursorMove() routine moves the cursor to a
- particular spot on the screen, and the
- vrl_VideoCursorSetAppearance() routine sets a new visual
- appearance for the cursor (the data that is pointed to by the app
- parameter varies from driver to driver).
-
- Display Routines
-
- The display subsystem is the "back end" of the rendering
- pipeline; it's responsible for actually drawing polygons (and
- lines, and text) into a raster.
-
- Internally, the display driver is just a function (much like
- the video driver, or any of the input device drivers); see
- Appendix H for information about how to write one. The
- application-visible functions that access that driver are
- described here.
-
- void vrl_DisplaySetDriver(vrl_DisplayDriverFunction driver);
-
-
- AVRIL Technical Reference Manual 37
-
-
-
-
-
- This function sets the display driver function to use; all
- subsequent calls to the vrl_Display family of routines will
- ultimately be passed to the specified function.
-
- int vrl_DisplayInit(vrl_Raster *raster);
- void vrl_DisplayQuit(void);
-
- These two routines are responsible for initializing and de-
- initializing the display subsystem. The raster parameter
- specifies a raster to use; this may be an off-screen buffer in
- system memory, or the actual physical framebuffer returned by
- vrl_VideoGetRaster().
-
- You can change the raster being used; to set or query the raster,
- use the following functions:
-
- void vrl_DisplaySetRaster(vrl_Raster *r);
- vrl_Raster *vrl_DisplayGetRaster(void);
-
- You can directly obtain the height, width and depth of the
- current display raster using the following routines:
-
- int vrl_DisplayGetWidth(void);
- int vrl_DisplayGetHeight(void);
- int vrl_DisplayGetDepth(void);
-
- You can obtain the current version of the display driver, and a
- string describing the driver, using the following functions:
-
- int vrl_DisplayGetVersion(void);
- char *vrl_DisplayGetDescription(void);
-
- The display subsystem contains routines for clearing the screen,
- drawing individual points (i.e. pixels), drawing lines, drawing
- boxes, and drawing text:
-
- void vrl_DisplayClear(vrl_Color color);
- void vrl_DisplayPoint(vrl_ScreenPos x, vrl_ScreenPos y, vrl_Color color);
- void vrl_DisplayLine(vrl_ScreenPos x1, vrl_ScreenPos y1, vrl_ScreenPos x2,
- vrl_ScreenPos y2, vrl_Color color);
- void vrl_DisplayBox(vrl_ScreenPos x1, vrl_ScreenPos y1, vrl_ScreenPos x2,
- vrl_ScreenPos y2, vrl_Color color);
- void vrl_DisplayText(vrl_ScreenPos x, vrl_ScreenPos y, vrl_Color color,
- char *message);
-
- When drawing a string of text, it's sometimes necessary to find
- out how wide and high it will appear on screen; the following two
- functions provide that information:
-
- vrl_ScreenPos vrl_DisplayGetTextWidth(char *string);
- vrl_ScreenPos vrl_DisplayGetTextHeight(char *string);
-
-
- AVRIL Technical Reference Manual 38
-
-
-
-
-
- The rendering engine (or the application) may need to find out
- what capabilities the display driver has; in particular, whether
- it can do things like Gouraud shading and X-Y clipping. The
- following routines provide the answers:
-
- vrl_Boolean vrl_DisplayCanGouraud(void);
- vrl_Boolean vrl_DisplayCanXYclip(void);
-
- When rendering, certain tasks have to be performed at the
- beginning and end of every frame; the application informs the
- display driver when a frame begins and ends using the following
- two functions:
-
- void vrl_DisplayBeginFrame(void);
- void vrl_DisplayEndFrame(void);
-
- Some display drivers are capable of Z-buffering, either in
- hardware or in software. The following routines are provided to
- support Z-buffers:
-
- vrl_DisplayUseZbuffer(flag)
- void vrl_DisplaySetZbuffer(vrl_Raster *r);
- vrl_Raster *vrl_DisplayGetZbuffer(void);
- void vrl_DisplayClearZbuffer(depth);
-
- These functions allow you to set and get pointers to the
- vrl_Raster that will be used as a Z-buffer (if software Z-
- buffering is used). The vrl_DisplayClearZbuffer() routine clears
- the currently-set Z-buffer (hardware or software) to the
- specified depth value. The vrl_DisplayUseZbuffer() routine tells
- the display driver whether or not to use the Z-buffer; the flag
- is non-zero if Z-buffering should be enabled, and the return
- value is 0 if no Z-buffer is present, 1 if a software Z-buffer is
- available, or 2 if a hardware Z-buffer is available. Note that
- as of version 2.0, AVRIL does not yet support Z-buffering.
-
- Some shading algorithms have greater computational expense
- than others do. It's possible to limit the complexity of the
- shading that the display driver uses by calling the following
- function:
-
- void vrl_DisplaySetShading(int value);
-
- The higher the value parameter, the more time is spent on shading
- (e.g. Gouraud versus flat, dithering enabled or disabled, etc).
- The exact meaning is up to the display driver.
-
- Updating the actual, physical display from the off-screen buffer
- is done by calling the routine
-
- void vrl_DisplayUpdate(void);
-
-
- AVRIL Technical Reference Manual 39
-
-
-
-
-
- For drivers that write straight to the physical framebuffer, the
- vrl_DisplayUpdate() function does nothing; for those that use
- off-screen buffers, it does the blit.
-
- Some display drivers need to perform certain re-calculations
- whenever the palette changes; to inform the display driver of a
- new palette, call the following routine:
-
- void vrl_DisplayUpdatePalette(vrl_Palette *palette);
-
- You can specify a rectangular on-screen window, to limit the area
- of the screen that the display driver will write to. You can
- also find out the location and size of that window. The
- functions to do so are as follows:
-
- void vrl_DisplaySetWindow(vrl_ScreenPos x1, vrl_ScreenPos y1, vrl_ScreenPos x2,
- vrl_ScreenPos y2);
- void vrl_DisplayGetWindow(vrl_ScreenPos *x1, vrl_ScreenPos *y1,
- vrl_ScreenPos *x2, vrl_ScreenPos *y2);
-
- Note that stereoscopic rendering may have an impact on the "real"
- windows being used.
-
- The display subsystem also has support for stereoscopic viewing.
- It understands certain types of viewing, and must be informed
- when the stereo type changes. You can set and query the stereo
- type using the following two functions:
-
- void vrl_DisplayStereoSetType(VRL_STEREO_TYPE stype);
- VRL_STEREO_TYPE vrl_DisplayStereoGetType(void);
-
- You can specify which "eye" is being drawn to, and which should
- be displayed, using the following functions:
-
- void vrl_DisplayStereoSetDrawEye(VRL_STEREO_EYE eye);
- VRL_STEREO_EYE vrl_DisplayStereoGetDrawEye(void);
- void vrl_DisplayStereoSetViewEye(VRL_STEREO_EYE eye);
- VRL_STEREO_EYE vrl_DisplayStereoGetViewEye(void);
-
- The eye parameter is one of the values VRL_STEREOEYE_LEFT or
- VRL_STEREOEYE_RIGHT.
-
- Some stereoscopic viewing systems subdivide the screen,
- putting the left-eye image in one area and the right-eye image in
- another; the two are then optically "shuffled" to the appropriate
- eye. The specific screen areas to use for each eye are set using
- the following functions:
-
- void vrl_DisplayStereoSetLeftWindow(vrl_ScreenPos x1, vrl_ScreenPos y1, vrl_ScreenPos x2,
- vrl_ScreenPos y2);
- void vrl_DisplayStereoSetRightWindow(vrl_ScreenPos x1, vrl_ScreenPos y1, vrl_ScreenPos x2,
- vrl_ScreenPos y2);
-
- AVRIL Technical Reference Manual 40
-
-
-
-
-
- And finally, some stereoscopic viewing systems use more than one
- display card. The following function is used to specify a
- "callback" or "upcall" function that should be called to select a
- specific card:
-
- void vrl_DisplayStereoSetCardFunction(void (*function)(VRL_STEREO_EYE));
-
- The callback function is told which card should be written to;
- the value is one of the constants VRL_STEREOEYE_NEITHER,
- VRL_STEREOEYE_LEFT, VRL_STEREOEYE_RIGHT or VRL_STEREOEYE_BOTH.
- The function will be called by the video subsystem in order to
- select either, neither or both of the video cards.
-
- PCX File Routines
-
- There are two functions that deal with files in PCX format:
-
- vrl_Boolean vrl_ReadPCX(FILE *in);
- vrl_Boolean vrl_WritePCX(FILE *out);
-
- The first one reads a PCX file into the current drawing page, the
- other writes the current drawing page out to disk as a PCX file.
-
- Devices
-
- AVRIL has support for input devices providing multiple "degrees
- of freedom" (DOF). In fact, AVRIL's devices are even more
- general; each device can have an arbitrary number of input and
- output channels.
-
- To use a device in AVRIL, you must first "open" it; this is
- analogous to opening a file. When you're finished with the
- device, you should "close" it; you can close all open devices
- using vrl_DeviceCloseAll(), which is set as an atexit() function
- by vrl_SystemStartup().
-
- vrl_Device *vrl_DeviceOpen(vrl_DeviceDriverFunction fn, vrl_SerialPort *port);
- void vrl_DeviceClose(vrl_Device *device);
- void vrl_DeviceCloseAll(void);
-
- Most input devices communicate over a serial port; the port
- parameter is a pointer to such a port that's been opened with
- vrl_SerialOpen(). See the section on Serial Ports for more
- details. Devices (such as the keyboard) that don't use a serial
- port should pass NULL as the port parameter. The fn parameter is
- a function that operates the device; there are a number of these
- already defined for popular devices, and it's easy to write your
- own if you have unusual devices you wish to support. They are
- listed in avrildrv.h, and in the cfg.c file; you should update
- those files as you add drivers.
-
-
-
- AVRIL Technical Reference Manual 41
-
-
-
-
-
- If you need to get a pointer to the serial port associated
- with a device, just call the following function:
-
- vrl_SerialPort *vrl_DeviceGetPort(vrl_Device *device);
-
- Devices can have a "mode" associated with them, whose meaning is
- specific to each device. You can set and get a device's current
- mode using these two functions:
-
- void vrl_DeviceSetMode(vrl_Device *device, int mode);
- int vrl_DeviceGetMode(vrl_Device *device);
-
- Devices can also have "nicknames"; for example, your application
- might deal with a head-tracker called "headtrack" which would be
- defined (in the configuration file, most likely) to be the device
- used for head tracking (e.g. a Polhemus Isotrak or a Logitech Red
- Baron). You can set and query the nickname of a device, or find
- a device with a particular nickname, using the following
- functions:
-
- char *vrl_DeviceGetNickname(vrl_Device *device);
- void vrl_DeviceSetNickname(vrl_Device *device, char *nickname);
- vrl_Device *vrl_DeviceFind(char *nickname);
-
- Once a device has been opened, you can easily find out how many
- input channels it has, and how many two-state buttons are on the
- device, using the following two functions:
-
- int vrl_DeviceGetNchannels(vrl_Device *device);
- int vrl_DeviceGetNButtons(vrl_Device *device);
-
- Sometimes devices can get into a strange state, or drift from
- their initial settings; the function vrl_DeviceReset() resets a
- device to the state it was in just after it was opened.
-
- int vrl_DeviceReset(vrl_Device *device);
-
- For many devices, resetting a device also marks the current
- values of all its channels as the "zero" value for that channel.
- To mark the current values as being the "maximum" values, call
- the function
-
- void vrl_DeviceSetRange(vrl_Device *device);
-
- Devices should be periodically "polled" to see if they have
- anything to report; this is normally done in the vrl_SystemRun()
- function. An individual device can be polled using
- vrl_DevicePoll(), which returns a non-zero value if new data was
- acquired. All the devices can be polled by calling
- vrl_DevicePollAll(), which returns a non-zero value if any of the
- devices had new data.
-
-
- AVRIL Technical Reference Manual 42
-
-
-
-
-
- int vrl_DevicePoll(vrl_Device *device);
- void vrl_DevicePollAll(void);
-
- You can get the current value of a channel's input by calling
- vrl_DeviceGetValue(), and you can read the button status on the
- device using vrl_DeviceGetButtons():
-
- vrl_Scalar vrl_DeviceGetValue(vrl_Device *device, int channel);
- vrl_unsigned32bit vrl_DeviceGetButtons(vrl_Device *device);
-
- Each bit corresponds to a single button on the device.
-
- The first six channels are special, since they correspond to
- the six basic degrees of freedom a device can have. The first
- three, whose channel numbers are the #defined values X, Y, and Z,
- provide the three-dimensional location of the input device in its
- private coordinate system. The next three, whose channel numbers
- are the #defined values XROT, YROT and ZROT, provide the rotation
- of the device around each of the three axes. Every device is
- expected to provide at least those six values; others, such as
- glove-like input devices, may have a separate channel for the
- flexion of each finger.
-
- You can determine whether a channel's value has changed
- since the previous poll by using vrl_DeviceChannelGetChanged(),
- and you can use vrl_DeviceGetChangedButtons() to obtain a
- vrl_unsigned32bit word whose bits indicate whether the
- corresponding buttons have changed state since the previous poll.
-
- vrl_Boolean vrl_DeviceGetChanged(vrl_Device *device, int channel);
- vrl_unsigned32bit vrl_DeviceGetChangedButtons(vrl_Device *device);
-
- Note that "previous poll" means the one prior to the most recent
- one; in other words, you would check the changed flags
- immediately after a call to vrl_DevicePoll() or
- vrl_DevicePollAll() in order to see if they've changed since the
- last time through.
-
- Some devices (such as the Logitech Cyberman and the Global
- Devices Controller) are capable of output as well as input. You
- can find out the number of output channels a device has using the
- following function:
-
- int vrl_DeviceGetNOutputChannels(vrl_Device *device);
-
- There are some devices that shouldn't be polled too frequently
- (possibly because the polling takes a long time). Devices
- drivers typically set their own polling frequency when they're
- initialized, but you can read and set the polling period using
- these two functions:
-
-
-
- AVRIL Technical Reference Manual 43
-
-
-
-
-
- void vrl_DeviceSetPeriod(vrl_Device *device, vrl_Time period);
- vrl_Time vrl_DeviceGetPeriod(vrl_Device *device);
-
- Some devices provide fewer than six degrees of freedom; in
- particular, some devices (such as sourceless head trackers)
- provide only rotational information, while others might provide
- only positional information. In addition, some axes are
- absolute, while others are relative; for example, a magnetic
- tracker provides absolute rotation, whereas a joystick usually
- provides a rate of rotation. Two functions are used to determine
- what a device's suggested modes of operation are for translation
- and rotation:
-
- vrl_DeviceMotionMode vrl_DeviceGetRotationMode(vrl_Device *device);
- vrl_DeviceMotionMode vrl_DeviceGetTranslationMode(vrl_Device *device);
-
- Each of these two functions returns one of the values
- VRL_MOTION_NONE (i.e., this type of motion is not reported by
- this device), VRL_MOTION_RELATIVE (i.e. this device provides
- relative information) or VRL_MOTION_ABSOLUTE (this device
- provides absolute information).
-
- It's important to note that these are all suggestions from
- the device driver as to how it should be used; you can still
- choose, in your application, to treat any device as either
- absolute or relative.
-
- To understand what these next few functions do, it's
- important to understand what kind of processing the system does
- on the values once it receives them from the device. Each
- channel can be in either "accumulate" or "non-accumulate" mode.
- For accumulating devices, the value is first checked to see how
- close it is to zero; if it's less than a channel-specific
- deadzone value, then the value is considered to be zero. For
- non-accumulating devices, the deadzone value is treated as a
- minimum change from the most recently read value for this
- channel; a device that moves by less than the deadzone amount
- between consecutive polls will not change in value.
-
- The value is then scaled so that its maximum value is less
- than a channel-specific scale value. For channels with the
- accumulate flag set, the value is also scaled by the elapsed
- time; the scale for such channels is treated as the maximum rate
- of change per second.
-
- The accumulate, scale and deadzone values can be set and read
- using the following calls:
-
- vrl_Scalar vrl_DeviceGetDeadzone(vrl_Device *device, int channel);
- void vrl_DeviceSetDeadzone(vrl_Device *device, int channel, vrl_Scalar value);
- vrl_Scalar vrl_DeviceGetScale(vrl_Device *device, int channel);
- vrl_DeviceSetScale(vrl_Device *device, int channel, vrl_Scalar value);
-
- AVRIL Technical Reference Manual 44
-
-
-
-
-
- vrl_Boolean vrl_DeviceGetAccumulate(vrl_Device *device, int channel);
- void vrl_DeviceSetAccumulate(vrl_Device *device, int channel, vrl_Boolean value);
-
- If you like, you can bypass all that processing and obtain the
- actual, "raw" value being reported by the device by calling
-
- vrl_Scalar vrl_DeviceGetRawValue(vrl_Device *device, int channel);
-
- Devices are kept internally in a linked list; if you want to
- iterate over the list, you can do it with the following two
- functions:
-
- vrl_Device *vrl_DeviceGetFirst(void);
- vrl_Device * vrl_DeviceGetNext(vrl_Device *device);
-
- You can retrieve a human-readable description of a device by
- calling the function
-
- char *vrl_DeviceGetDesc(vrl_Device *device);
-
- You can produce output on any of the device's channels by calling
-
- void vrl_DeviceOutput(vrl_Device *device, int channel, vrl_Scalar value);
-
- The channel and the value (which ought to be in the range 0 to
- 255) are passed along to the device; if it's capable of
- outputting that value on that channel, it does. Not all devices
- are capable of producing output, and those that can have a
- variety of different ways of doing it (including sound and
- vibration). All you can be sure of is that a value of zero will
- turn the output off, and a non-zero value will turn it on.
-
- Note that it's possible to have an "output-only" device; it
- will report zero for all its input values, but still respond to
- output requests. This might be one approach to supporting motion
- platforms, for example.
-
- Some 2D devices can map their two axes into 6 degrees of
- freedom using combinations of buttons. There are two functions
- to get and set the mapping tables they use:
-
- void vrl_DeviceSetButtonmap(vrl_Device *device, vrl_DeviceButtonmap *b);
- vrl_DeviceButtonmap *vrl_DeviceGetButtonmap(vrl_Device *device);
-
- Buttonmaps are a fairly complex topic, and are discussed in more
- detail in Appendix F.
-
- Serial Ports
-
- Since many input devices use serial communications, AVRIL
- contains a library of serial port routines. These will mostly be
-
-
- AVRIL Technical Reference Manual 45
-
-
-
-
-
- of interest to people writing device drivers, but they might also
- be used for modem communications.
-
- To some extent, serial port support will be platform-
- dependent; the meaning of the various parameters in the
- vrl_SerialOpen() call will be different on different systems.
- However, all the other routines should be the same regardless of
- platform.
-
- A serial port can be opened and closed using
- vrl_SerialOpen() and vrl_SerialClose() respectively; all the
- serial ports can be closed at once using vrl_SerialCloseAll(),
- which gets set as an atexit() function by vrl_SystemStartup().
- The communications parameters can be set using
- vrl_SerialSetParameters().
-
- vrl_SerialPort *vrl_SerialOpen(unsigned int address, int irq, unsigned int buffsize);
- void vrl_SerialClose(vrl_SerialPort *port);
- void vrl_SerialCloseAll(void);
- void vrl_SerialSetParameters(vrl_SerialPort *port, unsigned int baud,
- vrl_ParityType parity, int databits, int stopbits);
-
- The address parameter to vrl_SerialOpen() is interpreted
- differently on different platforms; on PC-compatible machines,
- it's the base address of the UART chip (usually 0x3F8 for COM1,
- 0x2F8 for COM2). The irq parameter is also system-dependent; on
- PC-compatible machines, it's the hardware interrupt level the
- serial port uses (usually 4 for COM1, 3 for COM2).
-
- The buffsize parameter is the size of buffer to use for
- incoming data. If it's set to zero, the port will be in a non-
- buffered mode; this may mean that characters get lost. Such a
- mode would only be used if you're doing your own handshake with
- the device; in other words, you send it a byte to poll it, and
- then sit in a tight loop receiving the resulting data. In this
- case, the irq value is ignored.
-
- The baud parameter to the vrl_SerialSetParameters() function
- is the baud rate; this is usually 9600 for most input devices.
- The parity parameter is one of VRL_PARITY_NONE, VRL_PARITY_EVEN
- or VRL_PARITY_ODD; most devices use VRL_PARITY_NONE. The
- databits field is the number of data bits per transmitted byte;
- this is either 7 or 8, and most devices use 8. The number of
- stop bits can be 1 or 2, and is usually 1. Newly-opened serial
- ports are set up to be 9600 baud, VRL_PARITY_NONE, 8 data bits
- and 1 stop bit.
-
- The vrl_SerialCheck() routine will return a non-zero value
- if there are unread characters in the input buffer (or if there's
- a character waiting at the UART, if the port is in unbuffered
- mode). The vrl_SerialGetc() routine reads and returns a byte.
- It should not be called unless you know there's a character
-
- AVRIL Technical Reference Manual 46
-
-
-
-
-
- waiting; in buffered mode, such a call will return zero, while in
- unbuffered mode the call will block until a character arrives!
- The vrl_SerialFlush() routine will get rid of any characters
- waiting in the input buffer.
-
- vrl_Boolean vrl_SerialCheck(vrl_SerialPort *port);
- unsigned int vrl_SerialGetc(vrl_SerialPort *port);
- void vrl_SerialFlush(vrl_SerialPort *p);
-
- The vrl_SerialPutc() and vrl_SerialPutString() routines put out
- single characters and null-terminated strings of characters
- respectively. The terminating null byte is not sent by
- vrl_SerialPutString().
-
- void vrl_SerialPutc(unsigned int c, vrl_SerialPort *port);
- void vrl_SerialPutString(unsigned char *s, vrl_SerialPort *p);
-
- There are also two routines for controlling the state of the DTR
- and RTS lines:
-
- void vrl_SerialSetDTR(vrl_SerialPort *port, vrl_Boolean value);
- void vrl_SerialSetRTS(vrl_SerialPort *port, vrl_Boolean value);
-
- and one for setting the size of the serial FIFO, if applicable:
-
- void vrl_SerialFifo(vrl_SerialPort *p, int n);
-
- Packet Routines
-
- Many serial devices communicate by sending "packets" of data.
- There are four routines in AVRIL to support the reception of
- packets:
-
- vrl_DevicePacketBuffer *vrl_DeviceCreatePacketBuffer(int buffsize);
- void vrl_DeviceDestroyPacketBuffer(vrl_DevicePacketBuffer *buff);
- vrl_Boolean vrl_DeviceGetPacket(vrl_SerialPort *port, vrl_DevicePacketBuffer *buff);
- unsigned char *vrl_DevicePacketGetBuffer(vrl_DevicePacketBuffer *buff);
-
- The vrl_DeviceCreatePacketBuffer() function creates a packet
- buffer with room for the specified number of bytes;
- vrl_DeviceDestroyPacketBuffer() destroys such a buffer. The
- vrl_DevicePacketGetBuffer() routine returns a pointer to the
- actual data packet.
-
- The vrl_DeviceGetPacket() routine is designed to handle a
- particular type of packet, a fixed-size one in which the leading
- byte has the top bit set and none of the other bytes do. This
- format is used by the Logitech Cyberman, among other devices.
- You can use this routine directly, or you can write your own
- (with a different name, of course); the source code is found in
- packet.c, and the vrl_DevicePacketBuffer data structure is in
- avril.h (and it's not expected to change, unlike many other
-
- AVRIL Technical Reference Manual 47
-
-
-
-
-
- internal data structures). The vrl_DeviceGetPacket() routine
- returns a non-zero value if a complete packet has been received
- (i.e. exactly buffsize bytes have been received, starting with a
- byte that has the top bit set).
-
- More information
-
- Remember that the appendices to this document are in a separate
- file, as is the Tutorial.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AVRIL Technical Reference Manual 48